stevens@hsi.UUCP (01/29/86)
I've found the two lines int x = 0; char *ptr = (char *) &x; acceptable to every C compiler I've used, until running into the Whitesmith's C compiler. They refuse to accept the type coercion "(char *)" on the second initialization. As I read K&R this should be acceptable through the rules initializer: = expression (Sec. 8.6) expression: ( type-name ) expression (Sec. 7.2) I talked to Whitesmiths about this and they are firm that their interpretation of the "standard" is that a type coercion following the equals sign is not allowed and they don't plan to change their compiler. Am I missing something ?? What does the proposed ANSI standard have to say about this ?? Richard Stevens Health Systems International, New Haven, CT ihnp4 ! hsi ! stevens
chris@umcp-cs.UUCP (Chris Torek) (01/30/86)
In article <302@hsi.UUCP> stevens@hsi.UUCP (Richard Stevens) writes: > I've found the two lines > int x = 0; > char *ptr = (char *) &x; > acceptable to every C compiler I've used, until running into the > Whitesmith's C compiler. They refuse to accept the type coercion > "(char *)" on the second initialization. ... > > I talked to Whitesmiths about this and they are firm that their > interpretation of the "standard" is that a type coercion following > the equals sign is not allowed and they don't plan to change their > compiler. Whitesmiths has never been one to do reasonable things with their compiler. Their interpretation is bogus. How a company can be so simultaneously good and bad at what they do is just amazing. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
keesan@bbncc5.UUCP (Morris M. Keesan) (01/31/86)
In article <302@hsi.UUCP> stevens@hsi.UUCP (Richard Stevens) writes: >I've found the two lines > > int x = 0; > char *ptr = (char *) &x; > >acceptable to every C compiler I've used, until running into the >Whitesmith's C compiler. They refuse to accept the type coercion "(char *)" >on the second initialization. As I read K&R this should be acceptable >through the rules > > initializer: > = expression (Sec. 8.6) > > expression: > ( type-name ) expression (Sec. 7.2) > >I talked to Whitesmiths about this and they are firm that their >interpretation of the "standard" is that a type coercion following the >equals sign is not allowed and they don't plan to change their compiler. My interpretation agrees with yours. Whitesmith are going by section 15, which enumerates the operators which are allowed in a constant expression, type-casting not being one of them. They are missing the additional information in paragraph 2 of 8.6, which increases the sorts of expression allowed, in particular allowing automatic variables to be initialized by "arbitrary expressions involving constants, and previously declared variables and functions." In any case, I'm not sure why you'd want to do what your example does, since the cast here is a no-op. -- Morris M. Keesan keesan@bbn-unix.ARPA {decvax,ihnp4,etc.}!bbncca!keesan
art@acc.arpa (02/01/86)
> I've found the two lines > > int x = 0; > char *ptr = (char *) &x; > > acceptable to every C compiler I've used, until running into the > Whitesmith's C compiler. They refuse to accept the type coercion "(char *)" > on the second initialization. As I read K&R this should be acceptable > through the rules The posting did not indicate whether the variables are static or auto. The initializer should be legal if x is static, but not neccesarily if x is declared as an auto. If x is auto, the compiler could place it in a register whose address cannot be taken. The compiler should be smart enough to notice the address operator and disallow register allocation. K&R only states that variables declared register cannot have their address taken. Anyone know what ANSI says? ------
jsdy@hadron.UUCP (Joseph S. D. Yao) (02/01/86)
In article <1450@bbncc5.UUCP> keesan@bbncc5.UUCP (Morris M. Keesan) writes: >In article <302@hsi.UUCP> stevens@hsi.UUCP (Richard Stevens) writes: >> int x = 0; >> char *ptr = (char *) &x; > In any case, I'm not sure why you'd want to do what your example does, >since the cast here is a no-op. Two reasons are immediately obvious. The less compelling is that lint tells you to. The more compelling is that on some computer architectures, e.g. one with type-tagged pointers, the cast may [ NOTE: n o t "will", just "may" ] not be a no-op. Some compilers will even reject the un-cast initialisation out of hand. Come to think of it, the 'lint' reason is not less compelling. Since you are doing something "unnatural" -- pointing to an object of one type with a pointer of another type -- this falls under the heading of explicitly having to say, "yes, this is not an error, I do mean to do exactly what this says." -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (02/02/86)
> > I've found the two lines > > > > int x = 0; > > char *ptr = (char *) &x; > > > > acceptable to every C compiler I've used, until running into the > > Whitesmith's C compiler. They refuse to accept the type coercion "(char *)" > > on the second initialization. As I read K&R this should be acceptable > > through the rules > > The posting did not indicate whether the variables are static or auto. The variables cannot be static, with those declarations. I assume you mean, file scope vs. block scope. In any case, it doesn't matter; the example is valid C code. (However, I wonder what it was trying to do. Treating the address of an int as a (char *) is rarely required, with fread/fwrite buffer parameter being the only common occurrence.) > The initializer should be legal if x is static, but not neccesarily if > x is declared as an auto. If x is auto, the compiler could place it in > a register whose address cannot be taken. That would be a compiler bug. Also, the presence or absence of the type cast would surely be irrelevant in such a case. > The compiler should be smart enough to notice the address operator and > disallow register allocation. K&R only states that variables declared > register cannot have their address taken. Anyone know what ANSI says? "The operand of the unary & operator must be a function locator or an lvalue that designates an object other than a bit-field or an object declared with the `register' storage-class specifier."
chris@umcp-cs.UUCP (Chris Torek) (02/02/86)
In article <2124@brl-tgr.ARPA> art@acc.arpa writes: > The initializer [for > int x = 0; char *ptr = (char *) &x; > ] should be legal if x is static, but not necessarily if x is > declared as an auto. If x is auto, the compiler could place it in > a register whose address cannot be taken. The compiler can only do this if (1) it can take the address of a register (a la Pyramid) or (2) it has determined that nowhere is the address actually taken. The compiler MUST NOT make `&var' illegal when `var' was not declared `register'. Another way to look at this is that `register' is not really a `hint to the compiler' about using a machine register, but rather a `promise to the compiler' that the programmer will not take the address of the variable. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
hrp@cray.UUCP (Hal Peterson) (02/03/86)
> > int x = 0; > > char *ptr = (char *) &x; > > In any case, I'm not sure why you'd want to do what your example does, > since the cast here is a no-op. An int pointer does not necessarily have the same format as a char pointer. Consider a word addressible machine on which the char's are packed into the words. -- Hal Peterson / Cray Research / 1440 Northland Dr. / Mendota Hts, MN 55120 UUCP: ihnp4!cray!hrp phone: (612) 681-3085
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/07/86)
>> > int x = 0; >> > char *ptr = (char *) &x; >> >> In any case, I'm not sure why you'd want to do what your example does, >> since the cast here is a no-op. > >An int pointer does not necessarily have the same format as a char pointer. >Consider a word addressible machine on which the char's are packed into the >words. But, the = forces the same type coercion as the type cast. Writing the cast explicitly is good style, however. I don't see why the fellow wants to do what he's doing quite apart from the question of how to express it..
ansok@spp3.UUCP (Gary Ansok) (02/08/86)
> int x = 0; > char *ptr = (char *) &x; Even if the pointers (int *) and (char *) have different formats, the assignment should take care of the conversion, so the cast should be unnecessary. A cast in an assignment var_1 = (type) var_2 is never strictly necessary, except for readability (a good reason!), to keep lint happy, or to work around bad compilers. (The cast *should* be acceptable to the compiler, though). As I understand it, a cast has the effect of an assignment to a temporary unnamed variable; sqrt((double) i) is equivalent to (tmp_double = i, sqrt(tmp_double)). Are there any other cases where casts are NEEDED besides: function calls: doub_var = sqrt((double) int_var); pointer punning: long_var = *(long *) char_ptr; Note: that last example is NONportable and downright dangerous on machines with alignment requirements. Still, it gets used by a lot of programmers (including me, on occasion...sigh). Gary Ansok {ihnp4,ucbvax,decvax}!trwrb!trwspp!spp3!ansok
msb@lsuc.UUCP (Mark Brader) (02/08/86)
In regard to... > > > int x = 0; > > > char *ptr = (char *) &x; > > In any case, I'm not sure why you'd want to do what your example does, > >since the cast here is a no-op. Joseph S. D. Yao responds... > Two reasons are immediately obvious... and goes on to give three reasons. Two are excellent, but the other is wrong: > ... on some computer > architectures, e.g. one with type-tagged pointers, the cast may > [ NOTE: n o t "will", just "may" ] not be a no-op. If this is not a slip, it stems from a misconception of casting which is a Frequently Repeated Error in this newsgroup. (If I remember what somebody posted a while ago, the error found its way into a DECUS C manual, which accounts for its widespreadness.) The cast specifies a conversion. If TTT and UUU are types, and we have: TTT t; UUU u; /* ..... */ t = u; then at that point the expressions t and (TTT)u are interchangeable. In the case of type-tagged pointers, the cast specifies that the pointer tagged "int" is to be converted to one tagged "char" and stored in the variable, but so would the initialization or assignment without the cast, if the compiler accepts it at all. Mark Brader [ The current ANSI draft C standard states: Preceding an expression by a parenthesized type name c o n v e r t s t h e v a l u e [ emphasis mine] of the expression to the named type. This construction is called a cast.]
throopw@dg_rtp.UUCP (02/09/86)
[ The case under discussion: int x = 0; char *ptr = (char *) &x; ] [keesan@bbncc5.UUCP] > > In any case, I'm not sure why you'd want to do what your example does, > >since the cast here is a no-op. [hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}] > Two reasons are immediately obvious. The less compelling is that > lint tells you to. The more compelling is that on some computer > architectures, e.g. one with type-tagged pointers, the cast may > [ NOTE: n o t "will", just "may" ] not be a no-op. Some compilers > will even reject the un-cast initialisation out of hand. Acutally, for K&R C, Keesan is correct. I was about to post just about what Yao posted, but I looked it up in K&R, and found two interesting points, the first about casts, and the second about initializations. [from The Book, page 42, paragraph 3, line 5, read in the style of a Gregorian chant for best effect] The precise meaning of a cast is in fact as if *expression* were assigned to a variable of the specified type, which is then used in place of the whole construction. [from The Book, page 198, paragraph 5] When an initializer applies to a *scalar* (a pointer or an object of arithmetic type), it consists of a single expression, perhaps in braces. The initial value of the object is taken from the expression; the same conversions as for assignment are performed. I'm not sure what ANSI says about it, but it's probably something similar. So, casts are equivalent to assignment, and initialization (for scalars) is equivalent to assignment, therefore initialization is equivalent to a cast, and the explicit cast is redundant. But I'd still put it in, myself, since > Come to think of it, the 'lint' reason is not less compelling. is right on the money... if you are doing something perverse like this with types, you had better justify yourself to lint (or some other typechecker). If you don't lint your code and pay attention to what lint says, you are just coding in a peculiar assembly language. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/10/86)
In article <269@spp3.UUCP> ansok@spp3.UUCP (Gary Ansok) asks: > Are there any other cases where casts are NEEDED besides: > > function calls: doub_var = sqrt((double) int_var); > pointer punning: long_var = *(long *) char_ptr; Type casts are also useful in expressions, to avoid introducing a temporary variable just to accomplish a type conversion. One example is casting a (char) to an (unsigned char) before putting it into an (int) variable, to prevent sign-extension. Another is casting a (long) to an (unsigned long) before a right-shift, to avoid sign-propagation. A third case is converting an (int) to a (long) early in an integer expression, to ensure that the operations will not overflow. But it is true that type casts should be used sparingly, and never to compensate for sloppiness in declaring data types. C note of the day: 'x' is of type (int), not (char).
jsdy@hadron.UUCP (Joseph S. D. Yao) (02/10/86)
In article <1100@lsuc.UUCP> msb@lsuc.UUCP (Mark Brader) writes: >In regard to... >> > > int x = 0; >> > > char *ptr = (char *) &x; >> > In any case, I'm not sure why you'd want to do what your example does, >> >since the cast here is a no-op. >Joseph S. D. Yao responds... >> Two reasons are immediately obvious... > >and goes on to give three reasons. Two are excellent, but the other is wrong: >> ... on some computer >> architectures, e.g. one with type-tagged pointers, the cast may >> [ NOTE: n o t "will", just "may" ] not be a no-op. (and this was the non-obvious, third reason.) >If this is not a slip, it stems from a misconception of casting which >is a Frequently Repeated Error in this newsgroup. ... >The cast specifies a conversion. ... >In the case of type-tagged pointers, the cast specifies that the >pointer tagged "int" is to be converted to one tagged "char" and >stored in the variable, but so would the initialization or assignment >without the cast, if the compiler accepts it at all. Perhaps this is my mistake, but I don't see what you have said that differs from mine. Yes, it specifies a conversion (if necessary). Therefore the cast may possibly not be a no-op. As you note, to even compile with some compilers, it may be required. Even if it is not required, however, then it is implicit and (possibly) not a no-op. The fact that it is required to be explicit on some machines and not cared about on others implies that you should use it if you desire that your code be more "portable". Does this explain why I say that it may not be a no-op? -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
nather@utastro.UUCP (Ed Nather) (02/11/86)
In article <792@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > C note of the day: 'x' is of type (int), not (char). *sigh* -- thanks, Doug. I just found that out yesterday, the hard way. The values of '\377' and -1 are one and the same without a type cast. Now, if I'd just read the news, instead of debugging ... -- Ed Nather Astronomy Dept, U of Texas @ Austin {allegra,ihnp4}!{noao,ut-sally}!utastro!nather nather@astro.UTEXAS.EDU
chris@umcp-cs.UUCP (Chris Torek) (02/12/86)
In article <354@utastro.UUCP> nather@utastro.UUCP (Ed Nather) writes: >In article <792@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn) writes: >> C note of the day: 'x' is of type (int), not (char). >The values of '\377' and -1 are one and the same without a type cast. Yes---*if* your machine has signed `char's. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
rb@ccivax.UUCP (rex ballard) (02/12/86)
In article <269@spp3.UUCP> ansok@spp3.UUCP (Gary Ansok) writes: > >Are there any other cases where casts are NEEDED besides: > > function calls: doub_var = sqrt((double) int_var); > pointer punning: long_var = *(long *) char_ptr; > Yes, accessing members of structures. ie: struct x y; struct i j; i.memb=y.memb; /* some compilers hate this */ should be written: i.memb= ((struct i)x).memb; this is especially true if both structures contain 'memb' but 'memb' is different type or placement. A union is probably preferred.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/14/86)
>The values of '\377' and -1 are one and the same without a type cast.
Well, on some architectures they are and on some they aren't.
X3J11 appears to have decided that they are the same whenever
a plain (char) is treated as (signed char); otherwise '\377'
has the value 255. I don't like this, but I suspect it's in
the rules for "historical reasons".
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/16/86)
In article <392@ccivax.UUCP> rb@ccivax.UUCP (What's in a name ?) writes: >In article <269@spp3.UUCP> ansok@spp3.UUCP (Gary Ansok) writes: >> >>Are there any other cases where casts are NEEDED besides: >> >> function calls: doub_var = sqrt((double) int_var); >> pointer punning: long_var = *(long *) char_ptr; >> > Yes, accessing members of structures. > ie: > struct x y; > struct i j; > i.memb=y.memb; /* some compilers hate this */ > should be written: > i.memb= ((struct i)x).memb; > > this is especially true if both structures contain 'memb' but > 'memb' is different type or placement. > A union is probably preferred. For the benefit of C novices: The above is nonsense; don't pay attention to it.
dan@BBN-PROPHET.ARPA (Dan Franklin) (02/18/86)
In article <3154@umcp-cs.UUCP> Chris Torek writes: > In article <354@utastro.UUCP> nather@utastro.UUCP (Ed Nather) writes: > >In article <792@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn) writes: > >The values of '\377' and -1 are one and the same without a type cast. > Yes---*if* your machine has signed `char's. AND if your machine has eight-bit bytes... Dan Franklin
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/19/86)
In article <1058@brl-smoke.ARPA> Dan Franklin <dan@BBN-PROPHET.ARPA> writes: >In article <3154@umcp-cs.UUCP> Chris Torek writes: >> In article <354@utastro.UUCP> nather@utastro.UUCP (Ed Nather) writes: >> >In article <792@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn) writes: >> >The values of '\377' and -1 are one and the same without a type cast. PLEASE fix the attributions when you post things. The above sequence makes it appear as if I said the attributed statement. Actually, if one looks really hard, he may discover that the attribution with my name in it should have been totally omitted. No big deal, but with silly software like this, people have to assume responsibility for clarity.
greg@utcsri.UUCP (Gregory Smith) (02/25/86)
>> >The values of '\377' and -1 are one and the same without a type cast.
I have lost of track of who originally said that, but it is presented as
evidence that '\377' ( or any char constant, e.g. 'x' ) is of type (int),
not of type (char). This is not evidence though, since
int x; x = 'a';
will convert 'a' to (int) if it was not already, before assigning. This
includes sign extending if that is the convention on your system. The same
applies to func('x') and case '\300':. Thus the equality between
-1 and '\377' does not mean that they are both int's. The only way to tell
is to do a sizeof('x'), which is 1 if 'x' is (char) and 2 or 4 or .. if 'x'
is int.
Having said this, I will add that char constants are in fact of type (int),
which can be verified by the above test. ( I speak for 4.2BSD).
Greg Smith
University of Toronto