throopw@dg_rtp.UUCP (02/19/86)
I'd like to correct a misleading and mistaken example posted in message <392@ccivax.UUCP>. You may consider this a flamage warning. >>Are there any other cases where casts are NEEDED besides: >> [some cases] In message <392@ccivax.UUCP> <rb@ccivax.UUCP (rex ballard)> says: > 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. Where to begin? Well, let's start out by pointing out that the 'i' in 'i.memb' must be a 'j' (both places), and the 'x' in '(struct i)x' must be a 'y'. I can't think of any reasonable way of making this fragment into a legal C program otherwise. Next, the definitions of 'memb' are missing, so I'm not sure what is meant by "different type or placement". Let's assume he means something like the following somewhat more complete example: struct s1 {int a; char b;}; struct s2 {char b; int a;}; void f(){ struct s1 x1; struct s2 x2; x1.a = x2.a; x1.a = ((struct s1)x2).a; } Ok, now with a complete example in hand, let's see what's what. To start with, Harbison and Steele says (sec 6.5, pg 129, chant along if you have the hymnal folks) An object of a structure or union type *T* may be converted only to a type that is the same as *T* (the trivial conversion). There is no change of representation, except that the bit patterns in any unused "holes" in the structure or union are not necessarily preserved. Amen. From this I predict that any adequate typechecker will get sick all over my complete example, and I am not let down by my favorite one. It points out the cast as illegal, and raises not a peep over the uncasted assignment that Rex claims might not work. I will even stick my neck out further and assert that any compiler which does not accept the uncasted expression is not a compiler for the C language. But what will a compiler do with the cast (as opposed to a typechecker, which had better complain)? Well, my handy-dandy "You Asked For It, You Got It" C compiler allocates the structs like so: | | | | | | | s1: |int a; (32 bits) |char b;|padding| s2: |char b;|padding|int a; (32 bits) | | | | | | | | For x1.a = x2.a, the compiler moves the 32 bits of integer in the s2 shaped record to the 32 bits of integer in the s1 shaped record. For the casted abomination, (got your barf bags ready?) it moves the 8 bits of b, plus the 8 bits of padding, plus the first 16 bits of a in the s2 shaped structure, and places them in the 32 bits of a in the s1 shaped structure. (Trust me. That's what it does. I tried it out.) Somehow I think that maybe (just maybe) Rex hasn't actually used his handy-dandy coding tip in any working program... what do y'all think? (Unless of course the posting was a joke, in which case I'd merely say that it was a moderately dangerous and ill-conceived joke.) -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
rb@ccivax.UUCP (rex ballard) (02/24/86)
Well, another goofup! First of all, the example given was poor to say the least. It certainly did not illustrate the problem. Your right, I've never used it, but I have seen it. An example where casting was needed was this. #define EOR 0370 char *x; if (*x<EOR) or #define EOR '\370' int *x; if (*x<EOR) (believe it or not, because of some #includes, both showed up in the same project, in fact, the definitions changed mid-project) guess what, the original compiler actually worked (gave the result desired) with the second example and didn't work with: #define EOR '\370' /* compiler treated like unsigned */ char *x; if(*x<EOR) because of the nature of what was actually desired, the proper definition would have been. #define EOR (unsigned char)0370 or #define EOR (unsigned char)'370' unsigned char x; if (*x<EOR) moral: when in doubt, cast (the next guy might figure out what you want) Qualifier: the compiler that gave this problem accepted code which contained so many syntax errors (missing semicolons...) that lint died just looking at it. (I think it was someone's kludge of bcpl or what they thought C was before reading K&R :-) It is a VERY OLD compiler. Please excuse problems in the code, these are just "off the cuff" examples, written near the end of the lunch hour.