1

Why does the given code give the following output.

#include <stdio.h>
int main(void) 
{
    int x = 0x12345678;
    unsigned short *p = &x;
    unsigned char *q = &x;
    printf("%x %x\n",*p++,*p++);
    printf("%x %x %x %x\n",q[0],q[1],q[2],q[3]);
    return 0;
}

Output:

1234 5678
78 56 34 12

and not:

1234 5678
12 34 56 78

The thing which I feel could be the answer is the endianness of the architecture must be causing it. But I can not comprehend how, because the whole 4-byte must be stored in a contiguous manner.

Also don't *q++ and *(q+1) point to the same address?

Rahul Shah
  • 165
  • 2
  • 11
  • `q++` has the value of `q` but is incremented *after* it's value has been returned. `q + 1` has the value of `q + 1`, which is different from `q`. – fuz Oct 03 '15 at 10:29
  • @πάντα ῥεῖ Why do you mark this **C** question a duplicate of a **C++** question? You do know that C and C++ are not the same language? – fuz Oct 03 '15 at 10:30
  • Even more, the linked question has a comment that *specifically states* that it should not be tagged as C as C has different rules regarding undefined behaviour. – fuz Oct 03 '15 at 10:31
  • @FUZxxl It was me removing the C++ tag. – πάντα ῥεῖ Oct 03 '15 at 10:32
  • @πάνταῥεῖ Then please explain this comment under the linked question: as an answer to the comment “I added the C tag, as this question/answer is valid in C as well.”: “@glglgl: No, it's not. C and C++ have their own divergent rules for this.” – fuz Oct 03 '15 at 10:33
  • @πάνταῥεῖ You have a golden tag badge in C, you should really know that C and C++ are subtly different and an answer to a question on technical details on one language is more often than not not applicable to the other language. – fuz Oct 03 '15 at 10:34
  • 1
    "*because* the whole 4-byte must be stored in a contiguous manner" is the very definiton of endianness. – Jongware Oct 03 '15 at 10:35
  • @Jongware how does that change the order of printing? – Rahul Shah Oct 03 '15 at 10:35
  • 1
    @RahulShah Generally, you can't post-increment the same variable twice in one statement. That results in an unspecified evaluation order. – fuz Oct 03 '15 at 10:38
  • @RahulShah On architectures like x86, data like integers are stored with little-endianess, meaning the least significant byte is stored first, … When fetching four contigous bytes with oneinstruction from memory, the processor takes care of the reordering and swaps (`bswap`) the bytes. When fetching just one byte, it obviously doesn't. – cadaniluk Oct 03 '15 at 10:39
  • @FUZxxl is correct. The problem is not in the line with separate bytes (even though it is endianness-dependend), but the 2-byte sequence provokes UB. – Jongware Oct 03 '15 at 10:40

1 Answers1

1

*q++ and *(q + 1) do not point to the same memory location during evaluation of their values in expressions. *q++ will point to the next memory location after q after the expression has been evaluated.

The reason you got 78 56 34 12 instead of 12 34 56 78 has to do with endianness; in memory your int is likely stored as 78563412. Try replacing q[0] thru q[3] in your printf statement with x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff and see if you get what you expected.

Logicrat
  • 4,438
  • 16
  • 22