We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
RVMDK v3.00a, Hello World sample for RealView compiler #pragma pack(1) unsigned char Buf[40]; int main (void) { *((short int *)&Buf[0]) = 0x77ff; *((int *)&Buf[2]) = 0x12345678; /* initialize the serial interface */ PINSEL0 = 0x00050000; U1LCR = 0x83; U1DLL = 97; U1LCR = 0x03; printf ("Hello World\n"); printf("%x %x %x %x \n", Buf[0],Buf[1],Buf[2],Buf[3]); } Hello World 78 56 34 12 ------------ The same thing is for CARM compiler 2.4, 2.5 What I am wrong ?
I think you missed Evegeny's point a bit because you understand a different thing under the term "typecast" than he does. U8 bytes[4]; U32 dest; ... dest = *(U32*)&bytes[0]; dest = *(U32*)&bytes[1]; dest = *(U32*)&bytes[2]; dest = *(U32*)&bytes[3]; [...] Without the typecast, the compiler could detect the misalignment. Not really. Without the casts, that snippet completely changes semantics. It becomes equivalent to four assignments of a char value to a U32 variable, like this:
U8 bytes[4]; U32 dest; ... dest = *(U32*)&bytes[0]; dest = *(U32*)&bytes[1]; dest = *(U32*)&bytes[2]; dest = *(U32*)&bytes[3];
dest = bytes[0]; dest = bytes[1]; dest = bytes[2]; dest = bytes[3];
then what about this one U8 bytes[4]; U32 dest; ... dest = (U32)&bytes[0]; dest = (U32)&bytes[1]; dest = (U32)&bytes[2]; dest = (U32)&bytes[3]; Erik
dest = (U32)&bytes[1]; This is equivalent to
dest = (U32)&bytes[1];
dest = (U32)(bytes + 1);
"Your example (like the one that started the thread) is about pointer casts, and those are forbidden by the C language. For good reason, too." Must be a different C language to the one I'm familiar with.
Ooops: Your example (like the one that started the thread) is about pointer casts, and those are forbidden by the C language. That was wrong, of course, sorry about that. So, to rectify it: Pointer casts are not forbidden by the language. But if you dereference a pointer after explicitly casting it, then basically only one of these situations can occur: 1) the pointer cast was superfluous --- you just cast back to a type that the pointer already had, or one compatible to it. 2) you get shot (a.k.a. "undefined behaviour"), because you violated the language at some step along the way. 3) you applied a compiler-specific extension. I.e. you were really writing "CA", "RealView" or "C51" code, which is quite similar to "C", but not really it. In a nutshell: every pointer cast is unportable, useless or wrong.
"But if you dereference a pointer after explicitly casting it, then basically only one of these situations can occur:" 4) You cast the pointer to a pointer to unsigned char and perfectly legitimately access the bytes of the object by dereferencing that pointer. "In a nutshell: every pointer cast is unportable, useless or wrong." Consider a 'C' implementation of the function scanf() as an example where pointer casting is portable, useful and correct.
4) You cast the pointer to a pointer to unsigned char and perfectly legitimately access the bytes of the object by dereferencing that pointer. Covered by the "unportable" case --- because the result is implementation-defined. It's essentially impossible that the bytes of the object, as stored by a particular C implementation, can be used portably. Consider a 'C' implementation of the function scanf() as an example where pointer casting is portable, useful and correct. There's no need to explicitly cast pointers to call or implement scanf(). All the necessary work can be done by implicit casts (e.g. those hidden in an assignment). Not even to mention that an implementation of scanf() cannot actually be portable.
"Covered by the "unportable" case --- because the result is implementation-defined." The result of dereferencing the pointer is the byte stored at the address pointed to. This is perfectly portable. "It's essentially impossible that the bytes of the object, as stored by a particular C implementation, can be used portably." On the contrary - there are many situations where bytes are manipulated without any knowledge of their content. Take memcpy() as an example. "There's no need to explicitly cast pointers to call or implement scanf()." No need, but it's a perfectly reasonable approach. "Not even to mention that an implementation of scanf() cannot actually be portable." Why do you think not?