Reputation: 1557
I have a struct in C:
typedef struct {
char member_a;
char member_b;
char member_c;
char member_d;
} mystruct;
From what I understand, C structs store their members in memory contiguously. If I print out the struct's memory I can see that is the case, but it looks like the order of the members is reversed.
mystruct m;
m.member_a = 0xAA;
m.member_b = 0xBB;
m.member_c = 0xCC;
m.member_d = 0xDD;
printf("%X\n", m);
This outputs:
DDCCBBAA
Is this because the struct's member's values are stored in memory in reverse order?
So the memory would look something like this, if m
was stored at memory location 0x00 and each location was 1 byte in size:
memory location | value |
---|---|
0x00 | 0xDD |
0x01 | 0xCC |
0x02 | 0xBB |
0x03 | 0xAA |
is this always the case with C? is this compiler specific? architecture specific? other?
Using gcc on Mac
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Upvotes: 2
Views: 1325
Reputation: 16120
The important thing to understand here is:
The textual representation of an integer says nothing about its internal representation. It is symbolic.
We accept that without a second thought for textual representations using base 10, or words: 65534 is as symbolic as sixtyfivethousandfivehundredthirtyfour.
But so is 0xfffe. It is a textual representation of an integral value that happens to be written using base 16 instead of base 10. By definition and definition only, borrowing from the decimal notation, digits to the left have higher values. This integral value, 65534, will always be written 0xfffe, no matter which bit pattern realizes it internally. This is one of the most important abstractions that the C programming language provides. It is the reason you always use the shift left operator for multiplication with 2, independent of the bit pattern and order the machine uses.
Any similarity to actual bit patterns, living or dead, is purely coincidental.
Upvotes: 1
Reputation: 31469
What you're doing is technically undefined behavior, so the compiler is allowed to do whatever it wants with it.
From what I understand, C structs store their members in memory contiguously.
Not really. But they are stored in the order they are declared.
If I print out the struct's memory I can see that is the case, but it looks like the order of the members is reversed.
That's because you're on a little endian machine. Try to add some more fields after the member_d
field. You will likely get the same result. But as I said, it's undefined behavior, so you have no guarantees.
Here is a snippet that illustrates it.
https://onlinegdb.com/uXS2sk142
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
int main(void) {
int32_t x = 0xDDCCBBAA;
char p[4];
memcpy(p, &x, 4);
for(int i=0; i<4; i++) {
printf("%X", p[i]);
}
}
It outputs this on a machine with little endian:
AABBCCDD
However, do note that a C compiler is free to add padding. So even if the order is guaranteed in memory, their position is not.
Related:
Detecting endianness programmatically in a C++ program
Upvotes: 2