Endian Issue, I Think

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// a 64-bit number, zeroed out for now
typedef unsigned long long UINT64;
UINT64 x = 0x0000000000000000;

// set the byte at the highest address to 0x80
// seems to me this should be endian agnostic
((unsigned char *)(&x))[7] = 0x80;

// print the bytes to verify
// 0000000000000080
int i;
for (i = 0; i < sizeof(x); i++) {
    printf("%02x", ((unsigned char *)(&x))[i]);
}

// rotate left 1 bit
// endian agnostic?
x = (x << 1) ^ (x >> 63);

// print the bytes again
// but now it's not at all what I expect
// 0100000000000000
for (i = 0; i < sizeof(x); i++) {
    printf("%02x", ((unsigned char *)(&x))[i]);
}
How is line 7 supposed to be "endian agnostic"?

Also, how is the output unexpected? You're printing the bytes from least to most significant.
80 hex = 1000 0000 binary. Naturally that 80 rotated left becomes a 1.
Last edited on
hamsterman is correct.

line 7 is subject to system endianness. On little endian machines you will be setting x to 0x8000000000000000, and on big endian machines you will be setting x to 0x0000000000000080

The rotate left on line 18 is fine (not subject to endianness)... although I would probably be using | instead of ^.

after the rotate you're left with:
0x0000000000000001 (little endian)
or
0x0000000000000100 (big endian)

and as hamsterman pointed out, you are printing the variable low byte first.
I suppose my confusion is because the value doesn't seem to simply rotate, but rather, the byte that was set seems to move from the highest address to the lowest address. Before the rotate, the bytes from lowest to highest are 0000000000000080. After the rotate, I'd expect the result to be 0000000000000100, but actually it's 0100000000000000. It actually swapped from the highest address to the lowest address (or so it appears to me).
The only way I can visualize...

0000000000000080
...becoming...
0100000000000000

...is to swap the byte order from...

0000000000000080
...to...
8000000000000000

...then right shift 7 bits, which doesn't make any sense.

I have very little doubt that the issue is with me, that I'm visualizing this in a very wrong way, but I need a little more help to see this the correct way.
Last edited on
Again, you are printing the number from least to most significant bytes. If you see 0000000000000080 it actually represents a number 0x8000000000000000 = 263. If you see 0100000000000000 it actually represents a number 0x0000000000000001 = 20. The first number has only the most significant bit set, the second one has only the least significant one. Naturally it takes one rotation to get from one to another.
To help illustrate what hamsterman is saying, try this:

1
2
3
4
5
6
x = 0x001122334455667788;

// then print how you're printing:
for (i = 0; i < sizeof(x); i++) {
    printf("%02x", ((unsigned char *)(&x))[i]);
}


You'll notice the number prints as 887766554433221100, which is backwards. This is because you're printing it "backwards" (low byte first instead of high byte first like you seem to be expecting)
Thanks for the help, everyone. Things have finally clicked in my brain.
Topic archived. No new replies allowed.