I know that a char and an int are calculated as being 8 bytes on 32 bit architectures due to alignment, but I recently came across a situation where a structure with 3 short
This link should help: http://en.wikipedia.org/wiki/Data_structure_alignment
In ThreeShorts
all members are two byte aligned.
That's because int
is 4 bytes, and has to be aligned to a 4-bytes boundary. This means that ANY struct
containing an int
also has to be aligned to at least 4-bytes.
On the other hand, short
is 2 bytes, and needs alignment only to a 2-bytes boundary. If a struct
containing short
s does not contain anything that needs a larger alignment, the struct
will also be aligned to 2-bytes.
It's entirely implementation-dependent, but presumably if your system can access any of the three short
s in the struct without worrying about the alignment, it can access any short
, and hence any data member, in an array of ThreeShorts
without worrying about alignment. Therefore there is no need to align the structs more strictly.
For the IntAndChar
example, int
presumably has size 4 and the implementation is concerned with its alignment. To ensure that every int
member in an array of IntAndChar
is properly aligned, the struct must be padded.
The sizeof
an array T[n]
is exactly defined as sizeof(T) * n
.
I don't know where you get the idea about char
or int
being calculated as "8 bytes". No, every type is calculated in accordance with its size: char
as 1, int
as 4 on a 32-bit platform (not 8, but 4). Alignment requirement for each type is normally the same as its size (although it doesn't have to be).
For this reason, when the structure contains the members of the same type, the total size of that structure will normally be the exact sum of the sizes of its members: a structure of 3 char
s will have size 3, and the structure of two int
s will have size 8.
Apparently type short
on your platform has size 2, so, expectedly, a structure of 3 shorts has size 6, which is exactly what you observe.
However, when your structure contains members of different types, then the difference between alignment requirements of different types comes into play. If the alignment requirement of the next field is stricter than the alignment requirement of the previous field, the compiler might have to add some padding bytes between these fields (to properly align the next member), which will affect the final size of the struct. Also, the compiler might have to add some extra padding bytes after the last member of the structure to satisfy alignment requirements in an array.
For example, a structure that looks as follows
struct S {
char c;
int i;
};
will most likely occupy 8 bytes on your platform because of the need for 3 padding bytes after the char
member. Note, char
counts as 1, int
as 4 and the extra 3 padding bytes between them make it 8.
Note also that this might easily introduce the dependency of the final size of the structure on the order in which the members are declared. For example, this structure
struct S1 {
char c1;
int i;
char c2;
};
on your platform will probably have size 12, while this one
struct S2 {
int i;
char c1;
char c2;
};
will occupy only 8 bytes. This last example is intended to illustrate that the final size of the structure cannot be expressed in terms of how many bytes each member "counts" for. The relationships between the members are also important.
Yep, I had the same issue. I have the following structure
struct Node{
short digit;
Node* next;
};
cout<<":"<<sizeof(Node)<<":"<<sizeof(short)<<":"<<sizeof(Node*)<<endl;
This gives me ::8:2:4 ?? why is the total sum for the structure = 8, but individual elements don't sum up?? This is because of memory alignment, the memory is padded with extra 2 bytes for alignment. Thanks
This really puzzles me, why isn't alignment enforced for t
What alignment do you want it to have ?
Shorts can be aligned on 2 byte boundaries with no ill effects(assuming common x86 compilers all over here..). So if you create an array of struct ThreeeShorts
, that struct having a size of 6 is fine, as any elements in such an array will start on a 2 byte boundary.
Your struct IntAndChar
contains an int, ints wants 4 byte alignment, so if you create an array of struct IntAndChar
the size have to be 8 for the next element to be aligned on a 4 byte boundary.
If we didn't consider arrays, it wouldn't matter much if struct IntAndChar
were 5 bytes long, the compiler would just allocate it starting on a 4 byte boundary when you create one one the stack, or use it as a compound member in another struct.
You can always get the number of elements in an array by doing sizeof(arrayofT)/sizeof(T), and array elements are guaranteed to be stored adjacently, such that the n'th element can be retreived by stepping N*sizeof(arrayelementtype) bytes from the start, and that's the main reason you'll see structs being padded at the end.