Issue
Assume we have a 64-bit x86 machine, which is little-endian and therefore stores the least-significant byte of a word in the byte with the lowest address. Assuming standard alignment rules for a 64-bit x86 Linux C compiler.
Consider
File 1:
#include <stdio.h>
struct cs {
int count;
unsigned short flags;
};
struct cs gcount;
extern void add_counter( int n );
int main(int c, char *argv[]);
int main(int c, char *argv[]) {
gcount.flags = 0xe700;
gcount.count = 1;
add_counter(42);
printf("count =%d\n", gcount.count);
return 0;
}
File 2:
struct cs {
unsigned short flags;
int count;
};
struct cs gcount = {0,0};
void add_counter (int n) {
gcount.count +=n;
}
If compiled the output is 1
.
Explanation:
count is defined as a strong global int the second file is thus initialized to {0,0}, here the order doesn't matter yet since it's just all zeroes.
A struct / type is defined per compilation unit so the first file uses the first definition to write to the struct meaning
gcount.flags = 0xe700; gcount.count=1;
cause the memory to look like
[e7 00 | 00 00 00 01] where (in little endian) the left is the top and the right is the bottom of memory.
(there's no padding between the two fields since short is at the end, sizeof will report 8B though)
when calling add_counter(42), the second file will use the second definition of cs and look at the memory as
[e7 00 00 00 | 00 01]
Now there's a 2B padding in between the two fields and the write access to the count will thus affect the range
[e7 00 00 00 | 00 01]
42 is 0x2a in hexadecimal (2*16 + 10) and will thus result in
[e7 2a 00 00 | 00 01]
converting this back to the view the first file has we get
[e7 2a | 00 00 00 01]
and thus the result is 1 instead of the expected 43.
Now I do get the general gist but I'm a bit confused about why we get [*e7 2a* 00 00 | 00 01]
when adding 42=0x2a
and not [*e7 00 00 2a | 00 01]
.
I'm expecting [*e7 00 00 2a | 00 01]
because we are using little-endian, meaning, the most right bit is the LSB. So e7
would actualy represent the most significant 8 bits here.
Solution
My disparaging comments about the exercise itself notwithstanding, it is possible to interpret the question as a simpler one about byte ordering. In that sense, the issue is with this assertion:
little-endian, meaning, the most right bit is the LSB.
Little-endian means that the bytes are ordered from least significant to most significant. The term having been coined in English and English being written left-to-right, that means the most left byte is the LSB in little-endian ordering.
Answered By - John Bollinger