lwh@romp.UUCP (lwh) (05/23/86)
My version of pcc on the IBM RT PC allows the following expression: struct abc { char d[500]; }; struct cba { char e[200]; }; struct cba *cbap; ((struct abc *)cbap)++; to increment cbap by 500. It appears that the ANSI standard doesn't say anything about the legality of this syntax. Does anyone have any experience or opinions on this subject? Larry Henson {ihnp4 | seismo | gatech}!ut-sally!im4u!esc-bb!romp!lwh The standard disclaimer: No one , not even me, is responsible.
greg@utcsri.UUCP (Gregory Smith) (05/26/86)
In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes: >My version of pcc on the IBM RT PC allows the following expression: > > struct abc { char d[500]; }; > struct cba { char e[200]; }; > struct cba *cbap; > > ((struct abc *)cbap)++; > > >to increment cbap by 500. It appears that the ANSI standard doesn't say >anything about the legality of this syntax. > First, a technical point: There is nothing wrong with the `syntax', which is identical to the syntax of (( struct foobar * ) pp )++; The *semantics*, though, are a different question. You are saying 'Treat cbap as a pointer to a (struct abc); increment that pointer'. The compiler dutifully adds 500. ( You asked for it, you got it... ) This is perfectly legal, but lint might well want to prod you about it... Since you are explicitly casting the pointer, though, it should be plain that you have good reasons to do so. -- "We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
jss@ulysses.UUCP (Jerry Schwarz) (05/28/86)
In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes: >My version of pcc on the IBM RT PC allows the following expression: > > ((struct abc *)cbap)++; > > >to increment cbap by 500. It appears that the ANSI standard doesn't say >anything about the legality of this syntax. "++" requires an lvalue. A cast produces a value but not an lvalue, so this is not legal in ANSI (or in K&R ) C. Jerry Schwarz Bell Labs, MH Comment: Many C compilers (especially those derived from pcc) have a tendency to "extend C by convenience". That is, they have an algorithm that generates code on correct C programs. They give an error message only when that algorithmn runs into trouble. On some illegal programs the algorithm doesn't run into any problems and so they generate code anyway. In this case, I guess that the compiler does not keep track of whether an expression is an lvalue in the "syntax" rather it detects it in the "semantics". In some circumstances it implements a cast applied to an "identifier" by changing the data structure to pretend that the "name" has the modified type. The combination of these two results in the behavior you observe.
rgh@inmet.UUCP (05/31/86)
> My version of pcc on the IBM RT PC allows the following expression: > > struct abc { char d[500]; }; > struct cba { char e[200]; }; > struct cba *cbap; > > ((struct abc *)cbap)++; > > to increment cbap by 500. It appears that the ANSI standard doesn't say > anything about the legality of this syntax. This is covered in the draft Standard: (1) a cast does not yield an lvalue; (2) the operand of post-inc must be an lvalue. So the construct is illegal. Standard-conforming syntax using the same idea is #define LCAST(typeP, lvalue) ( *( (typeP *) &lvalue ) ) #define INC_BY_SIZEOF(ptr, typeD) ( LCAST(typeD *, ptr)++ ) INC_BY_SIZEOF(cbap, struct abc); Semantically this works only so long as the type that ptr points to has the same alignment requirement as typeD , and (a more subtle point) as long as typeP has the same representation as ptr . Randy Hudson {ihnp4,cca!ima}!inmet!rgh
throopw@dg_rtp.UUCP (Wayne Throop) (06/01/86)
> greg@utcsri.UUCP (Gregory Smith) >> lwh@romp.UUCP (lwh) >>My version of pcc on the IBM RT PC allows the following expression: >> ((struct abc *)cbap)++; >>to increment cbap by 500. It appears that the ANSI standard doesn't say >>anything about the legality of this syntax. Well, no. It says that the *syntax* is legal. The *semantics* of such an increment are explicitly outlawed. A cast does *not* mean and *never* *has* meant to "treat the bits as a new type". It means *convert* the bits to the new type, and this conversion is machine dependant, and *never* results in an lvalue. > First, a technical point: There is nothing wrong with the `syntax', Right, right. > The *semantics*, though, are a different question. Yes, yes. > You are saying > 'Treat cbap as a pointer to a (struct abc); increment that pointer'. No, no. That may be what lwh *meant*, but that's not what he *said*. What he *said* was to increment a non-lvalue expression. Just as meaningful as saying "(i+j)++". Which is to say, not very meaningful. > The compiler dutifully adds 500. ( You asked for it, you got it... ) Well, *his* compiler dutifully adds an ammount large enough to reach the next (struct abc), which on his machine happens to be 500. Rephrasing, there are two interesting issues here. First, the fact that the compiler allows a cast to be used as an lvalue is bogus in the first place. That compiler, quite simply, allowed an illegal operation. In the second place, performing the increment-by-1 operation on a (struct abc *) is a machine-dependant operation, which on lwh's machine happens to change the pointer's bit-pattern in such a way that, if that bit pattern had been a twos-complement integer, we would have said it was incremented by 500. As I say, machine dependant to the max. > This is perfectly legal, but lint might well want to prod you about it... It is *not* legal, perfectly or imperfectly. And lint *had* *better* prod you about it. (It does, by the way. It says "illegal lhs of assignment".) > Since you are explicitly casting the pointer, though, it should be plain > that you have good reasons to do so. As may be. But once you have cast the pointer, you cannot use the cast expression as an lvalue. K&R say this is illegal, Harbison and Steele say this is illegal, and the ANSI draft says this is illegal. I mean, when the Father, the Son, and the Holy Ghost say it's illegal, I say it is then, now, and evermore, *ILLEGAL*. -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
ron@brl-sem.ARPA (Ron Natalie <ron>) (06/01/86)
In article <1273@ulysses.UUCP>, jss@ulysses.UUCP (Jerry Schwarz) writes: > In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes: > > ((struct abc *)cbap)++; > >to increment cbap by 500. It appears that the ANSI standard doesn't say > >anything about the legality of this syntax. > > "++" requires an lvalue. A cast produces a value but not an lvalue, > so this is not legal in ANSI (or in K&R ) C. I find this disgusting but ( *((struct abc **)&cbap) )++; would work. INEWS SUCKS INEWS SUCKS INEWS SUCKS INEWS SUCKS
chris@umcp-cs.UUCP (Chris Torek) (06/01/86)
Incidentally, if you really *do* want to take a pointer `p' to type `x', but treat it as a pointer to type `y', the construct *(y **)&p works (as long as `p' is addressable). Thus ((struct abc *)cbap)++; is not legal, but (*(struct abc **)&cbap)++; is (again, if cbap is addressable). What it means is machine dependent! -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
greg@utcsri.UUCP (Gregory Smith) (06/01/86)
In article <378@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes: >there are two interesting issues here. First, the fact that the >compiler allows a cast to be used as an lvalue is bogus in the first >place. That compiler, quite simply, allowed an illegal operation. [me:] >> This is perfectly legal, but lint might well want to prod you about it... > >It is *not* legal, perfectly or imperfectly. And lint *had* *better* >prod you about it. (It does, by the way. It says "illegal lhs of >assignment".) >...once you have cast the pointer, you cannot use the cast >expression as an lvalue. K&R say this is illegal, Harbison and Steele >say this is illegal, and the ANSI draft says this is illegal. I mean, >when the Father, the Son, and the Holy Ghost say it's illegal, I say it >is then, now, and evermore, *ILLEGAL*. >-- >Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw I stand corrected. I couldn't find anything explicitly forbidding or allowing this in K&R, ( I still can't ) so I gave that compiler the benefit of the doubt, without trying it here. Reasonable semantics could be defined for the operation, but I don't know how useful it is. -- "We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
david@sun.uucp (David DiGiacomo) (06/04/86)
In article <1764@umcp-cs.UUCP> chris@maryland.UUCP (Chris Torek) writes: >Incidentally, if you really *do* want to take a pointer `p' to >type `x', but treat it as a pointer to type `y', the construct > > *(y **)&p > >works (as long as `p' is addressable). Thus > > ((struct abc *)cbap)++; > >is not legal, but > > (*(struct abc **)&cbap)++; > >is (again, if cbap is addressable). What it means is machine >dependent! This is disgusting... why not use cbap = (struct cba *) ((caddr_t) cbap + sizeof(struct abc)); ? -- David DiGiacomo {decvax, ihnp4, ucbvax}!sun!david david@sun.arpa Sun Microsystems, Mt. View, CA (415) 960-7495
throopw@dg_rtp.UUCP (Wayne Throop) (06/07/86)
> greg@utcsri.UUCP (Gregory Smith) > I stand corrected. I couldn't find anything explicitly forbidding or > allowing this in K&R, ( I still can't ) so I gave that compiler the > benefit of the doubt, without trying it here. For those interested, here are the places that make ((T *)P)++ illegal. First, in K&R, two places. In the reference section, 7.2, unary operators: An expression preceeded by the parenthesized name of a data type causes conversion of the value of the expression to the named type. This construction is called a cast. Note that the *value* is *converted*. K&R are careful to call lvalues lvalues, and the note that a cast works on the value of the expression is noteworthy. Note also that this value is *converted*. It is *not* "taken as a new type". As an interesting digression, this is probably the source of much confusion over casts, since many think that they are conversion sometimes, and "look at T1-type bits through T2-colored glasses" other times. This is *not* the case... a cast is *always* a conversion. In C there are only two ways to take T1-typed-bits as if they were T2-typed-bits. Put the bits into a union of T1 and T2, or cast a pointer to them. (Well, they are the only two ways I could think of, anyhow.) Then note, in 5, objects and lvalues: The discussion of each operator below indicates whether it expects lvalue operands and whether it yields an lvalue. Casts do not state that they yield lvalues, and postincrement expects one. So the combination is semantically illegal according to K&R. In Harbison and Steele, things are simpler. In chapter seven, they list the operators that yield lvalues, which are e1[e2], (e) {if e is lvalue}, e.name {if e is lvalue} e->name, and *e and conclude the paragraph, saying No other form of expression can produce an lvalue. And in the same section, they state that postincrement requires an lvalue. The ANSI draft says in section 3.4 Note: A cast does not return an lvalue. As I say, Father, Son and Holy Ghost all agree on this point. > Reasonable semantics > could be defined for the operation, but I don't know how useful it is. On first glance, it *does* seem reasonable. But upon more detailed thought, it turns out not to be the case. The whole point is that reasonable semantics *cannot* be defined for the operation in a machine independant way. The reasoning of the ANSI folks is spelled out in the May '86 Dr. Dobb's Journal on page 20 in a section titled "Beating Dead Horses" if you want to look it up, but the short form of this argument is fairly simple. You say that ((T *)P)++ can be given reasonable semantics. This either means that pointers are drastically different from other types (in ways that are inconvenient and/or arbitrary), or this construction can also be given reasonable semantics: ((T)L)++ Filling in something concrete for the type and the lvalue, and assuming that "i" is an integer lvalue: ((float)i)++ Do you really want to contend that this is reasonable? If so, what does it mean? Either the semantics of C must be made very irregular and strange to allow ((T *)P)++, or the notion of any cast being an lvalue must be discarded. In addition to complexity and irregularity, possible semantics of casts of lvalues *being* lvalues are extremely machine dependant (in particular (in current implementations that allow them), the pointer cases depend on the pointer format for all pointer types being identical). This is *not* something that is "reasonable" to add to an allegedly machine independant language. -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
throopw@dg_rtp.UUCP (Wayne Throop) (06/08/86)
> david@sun.UUCP (David DiGiacomo) >> chris@maryland.UUCP (Chris Torek) >> ((struct abc *)cbap)++; >>is not legal, but >> (*(struct abc **)&cbap)++; >>is (again, if cbap is addressable). What it means is machine >>dependent! > This is disgusting... why not use > cbap = (struct cba *) ((caddr_t) cbap + sizeof(struct abc)); Because the latter construct mentions "cbap" twice. Thus, if this type of expression were embedded in a macro, "cbap" had better not contain side effects. Also, if "cbap" is difficult or complicated (you know, something like (*f1(a[s1][e1+e2],f2())) or worse), then expanding it twice might be undesirable even if it *were* side effect free. In short, it is indeed *useful* to do such things, just as things like (i += 2) are useful... but nobody has found a way to give the language sensible, consistent semantics if such a thing is allowed. Now, I know what you're thinking. You're thinking, ok, so why not cbap += (sizeof(struct abc) / sizeof(struct cba)); (assuming that the division has no remainder, of course, as might often be the case, or as may be arranged to be the case.) Well, because this isn't a post-increment construct, and that is what the whole thing started out over... somebody noticed that the pcc allows a post-increment on a cast of a pointer for some machines. The moral is, it just isn't possible to avoid mentioning an instance twice in all possible perverse cases. Sad but true. If it is really important to mention an instance only once, and then get at that instance many times, a binding-by-reference would work: { T *p = &reference_of_type_T_that_i_only_want_to_mention_once; ... *p ... *p ... *p ... } Now you can use the object that the complicated reference mentions as an lvalue many times, yet only evaluate it once. Yes, you are right... it *isn't* pretty. But sometimes a Programmer's gotta do what a Programmer's gotta do, a-yuh. -- "Now men, we've got uh new villuge ta raid. I want ya ta kill all the men, round up all the livestock, an' ravage all the wimmun. An' fer *God*'s *sake* get it *right* this time!" Rich Little as John Wayne, in the role of Ghengis Khan. -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
rgh%inmet.uucp@BRL.Arpa (06/10/86)
Return-Path: <info-c-request@BRL.ARPA> Redistributed: Xerox-Info-C^.x@XEROX.ARPA Received: from BRL-AOS.ARPA by Xerox.COM ; 02 JUN 86 16:42:06 PDT Received: from brl-smoke.arpa by AOS.BRL.ARPA id a015894; 2 Jun 86 17:10 EDT Received: from USENET by SMOKE.BRL.ARPA id a005080; 2 Jun 86 16:42 EDT Newsgroups: net.lang.c Message-ID: <5000043@inmet> Nf-ID: #R:romp.UUCP:114:inmet:5000043:000:919 Nf-From: inmet.UUCP!rgh May 31 14:55:00 1986 > My version of pcc on the IBM RT PC allows the following expression: > > struct abc { char d[500]; }; > struct cba { char e[200]; }; > struct cba *cbap; > > ((struct abc *)cbap)++; > > to increment cbap by 500. It appears that the ANSI standard doesn't say > anything about the legality of this syntax. This is covered in the draft Standard: (1) a cast does not yield an lvalue; (2) the operand of post-inc must be an lvalue. So the construct is illegal. Standard-conforming syntax using the same idea is #define LCAST(typeP, lvalue) ( *( (typeP *) &lvalue ) ) #define INC_BY_SIZEOF(ptr, typeD) ( LCAST(typeD *, ptr)++ ) INC_BY_SIZEOF(cbap, struct abc); Semantically this works only so long as the type that ptr points to has the same alignment requirement as typeD , and (a more subtle point) as long as typeP has the same representation as ptr . Randy Hudson {ihnp4,cca!ima}!inmet!rgh
davidsen@steinmetz.UUCP (Davidsen) (06/12/86)
In article <1273@ulysses.UUCP> jss@ulysses.UUCP writes: >In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes: >>My version of pcc on the IBM RT PC allows the following expression: >> >> ((struct abc *)cbap)++; >> >> >>to increment cbap by 500. It appears that the ANSI standard doesn't say >>anything about the legality of this syntax. > >"++" requires an lvalue. A cast produces a value but not an lvalue, >so this is not legal in ANSI (or in K&R ) C. > >Jerry Schwarz >Bell Labs, MH The variable 'cbap' is a pointer. The cast '(struct abc *)' is a pointer cast. I can use '((struct abc *)cbap)' with indirects and subscripts and anywhere that I can use an Lvalue, so I really believe that the expression is legal. Now, as to being *portable*. There is some language in the X3J11 proposed standard about possible loss of information and non-portability when pointers are cast. This is why the 'void *' type was introduced (in part) to have a pointer which could hold any valid data address. However, there is no guarantee that when the address of one data type, however obtaining, is cast to a pointer to another data type that the result will be valid. If I recall correctly the term in use in X3J11 for stuff was "valid but non-portable". Sorry I can't remember for sure who said it. I hope this clarifies the question somewhat (it does in my mind, anyway). -- -bill davidsen ihnp4!seismo!rochester!steinmetz!--\ \ unirot ------------->---> crdos1!davidsen / sixhub ---------------------/ (davidsen@ge-crd.ARPA) "Stupidity, like virtue, is its own reward"
throopw@dg_rtp.UUCP (Wayne Throop) (06/14/86)
> davidsen@steinmetz.UUCP (Davidsen) [discussing the illegal C expression ((struct abc *)cbap)++] > The variable 'cbap' is a pointer. Correct. > The cast '(struct abc *)' is a pointer cast. Correct. > I can use '((struct abc *)cbap)' with indirects and subscripts Correct. > and anywhere that I can use an Lvalue, "Non sequitur. Your thinking is un-co-ordinated." Wrong. I say again, ****WRONG****. The "lvaluehood" of an expression is *NOT* *NOW*, and *HAS* *NEVER* *BEEN*, implied by the legality of the use of that expression in pointer arithmetic and indirection. You don't seem to know what an lvalue is, nor do you seem to know what entities in C are lvalues. An lvalue is an expression that can appear as the left subexpression of an assignment operator. Saying that a cast is an lvalue is as nonsensical as saying that (a+b) is an lvalue, or that (&x) is an lvalue. Casts do *NOT* yeild lvalues. They *DO* *NOT* *NOW*, and they *NEVER* *HAVE*. God willing they *NEVER* *WILL*. I appologize for my vehemence, but this issue comes up over and over and over and over and over and over and over and over and over. And over. I am using caps and stars to try to *GET* *YOUR* *ATTENTION*!!!!! *HEY*!!! *ANYBODY* *IN* *THERE*???? *CASTS* *NEVER* *YIELD* *LVALUES*!!!!!!!!!!!! *NEVER*!!!!!!!! ********* N E V E R *******!!!! **N**O**T** **E**V**E**R**!!!!!!!!!!!! I have posted references in K&R and the ANSI draft standard that support my position. I have posted a reference to a recent Dr Dobbs where the issue was discussed in endless boring detail. Those that think otherwise say things like this: > so I really believe that the expression is legal. Great. And my aunt Martha believes pigs can fly. She is wrong. And so are you. My appologies if my prior postings simply didn't arive at your site. My appologies for any offense I may have given. And in general, profuse appology for my state of extreme annoyance and exasperation. But, confound it, I am right about this, and you are wrong, and yet people that hold this incorrect opinion keep posting and posting and posting and posting. It's a conspiracy, I tell you! You're all out to *GET* me! But you won't... no, I won't *LET* you! Get them *OFF* me, get them **OFF**, spiders, can't you *SEE* them, they're crawling all ****OVER**** me.... AAAAAAAUUUUUUUGGGGGGGHHHHHHH!!!!!!!! -- Well, I feel a *little* better after the sedation. But shouting *does* exhaust one so. -- What's that? You say you want the references again? They were - K&R, sections 7.2 and 5 in the reference part. - Harbison and Steele, first few paragraphs of chapter 7. - ANSI draft standard, section 3.4. - Dr. Dobbs Journal, May 1986, page 20, under the heading "Beating Dead Horses" (most appropriate!) -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
jss@ulysses.UUCP (Jerry Schwarz) (06/15/86)
> > The variable 'cbap' is a pointer. The cast '(struct abc *)' is a > pointer cast. I can use '((struct abc *)cbap)' with indirects and > subscripts and anywhere that I can use an Lvalue, so I really believe > that the expression is legal. > -bill davidsen Being a pointer value is not the same as being an lvalue. The places that require lvalues are left hand side of assignments, and operands of the increment and decrement operations. In none of these locations is '((struct abc*)cbap)' legal. If p is an expression with a (data) pointer type then *p will be an lvalue, so ++ *((struct abc**)&cbab) will modify cbab. Jerry Schwarz Bell Labs, MH
kenny@uiucdcsb.CS.UIUC.EDU (06/17/86)
/* Written 11:52 am Jun 12, 1986 by davidsen@steinmetz.UUCP in uiucdcsb:net.lang.c */ >In article <1273@ulysses.UUCP> jss@ulysses.UUCP writes: >>In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes: >>>My version of pcc on the IBM RT PC allows the following expression: >>> >>> ((struct abc *)cbap)++; >>> >>> >>>to increment cbap by 500. It appears that the ANSI standard doesn't say >>>anything about the legality of this syntax. >> >>"++" requires an lvalue. A cast produces a value but not an lvalue, >>so this is not legal in ANSI (or in K&R ) C. >> >>Jerry Schwarz >>Bell Labs, MH > >The variable 'cbap' is a pointer. The cast '(struct abc *)' is a >pointer cast. I can use '((struct abc *)cbap)' with indirects and >subscripts and anywhere that I can use an Lvalue, so I really believe ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- NO! >that the expression is legal. > >Now, as to being *portable*. There is some language in the X3J11 >proposed standard about possible loss of information and >non-portability when pointers are cast. This is why the 'void *' type >was introduced (in part) to have a pointer which could hold any valid >data address. However, there is no guarantee that when the address of >one data type, however obtaining, is cast to a pointer to another data >type that the result will be valid. > >If I recall correctly the term in use in X3J11 for stuff was "valid but >non-portable". Sorry I can't remember for sure who said it. I hope this >clarifies the question somewhat (it does in my mind, anyway). [ ... ] /* End of text from uiucdcsb:net.lang.c */ No, no, no! You can *dereference* ((struct abc *) cbap). You can subscript it, you can put a * in front of it, you can use it anywhere you can use a pointer *rvalue*. What you can't do is use it in any context requiring an *lvalue*. You can't ++ it, you can't -- it, you can't = (+=, -=, ...) into it, and you can't put an & in front of it. If you wanted to force incrementation of cbap as a (struct abc *) and throw portability to the winds, and you know that different types of pointer share the same representation on your machine, you might try ++*((struct abc **) &cbap). I wouldn't. Now, class, three times slowly: Casts are rvalues. Casts are rvalues. Casts are rvalues. Kevin Kenny University of Illinois at Urbana-Champaign UUCP: {ihnp4,pur-ee,convex}!uiucdcs!kenny CSNET: kenny@UIUC.CSNET ARPA: kenny@B.CS.UIUC.EDU (kenny@UIUC.ARPA) "Yes, understanding today's complex world is a bit like having bees live in your head, but there they are."
davidsen@steinmetz.UUCP (Davidsen) (06/24/86)
In article <1295@ulysses.UUCP> jss@ulysses.UUCP (Jerry Schwarz) writes: >> >> The variable 'cbap' is a pointer. The cast '(struct abc *)' is a >> pointer cast. I can use '((struct abc *)cbap)' with indirects and >> subscripts and anywhere that I can use an Lvalue, so I really believe >> that the expression is legal. >> -bill davidsen > >Being a pointer value is not the same as being an lvalue. The places >that require lvalues are left hand side of assignments, and operands >of the increment and decrement operations. In none of these locations >is '((struct abc*)cbap)' legal. >> subscripts and anywhere that I can use an Lvalue, so I really believe ^^^^^^ A thousand pardons! I was thinking about Lvalues, and wrote Lvalue where I meant "address value". The point I was making (trying to amke) was that the result of the cast operation is legen *in* an Lvalue, where a pointer would be, not that I thought it was an Lvalue as is. Example: *((float *) ptr) = 4.5; /* ptr is char * type */ The other question was the legality of a cast on increment, and rather than read books and standards, I actually tried it, based on the theory that what happened in most places is "current practice". So far I have found 3 of seven compilers which compile code for ((float *) ptr)++; /* ptr type is char * */ so I make no claims one way or the other. NOTE: I am not claiming that either of these is portable or useful, but that's not the same thing as valid. Current practice is why enums are done as integers rather than being truly a distinct data type. They were added because the preprocessor ran out of symbol space as far as I know. Thanks to the people who pointed out the poor explanation in the earlier posting. All were polite except one jerk who sent six screens of flames and a ficticious .signature at the end. I hope this didn't confuse anyone. -- -bill davidsen ihnp4!seismo!rochester!steinmetz!--\ \ unirot ------------->---> crdos1!davidsen chinet ------/ sixhub ---------------------/ (davidsen@ge-crd.ARPA) "Stupidity, like virtue, is its own reward"