In this article I assume that the computer's word size is 4 bytes(IA32), because the main idea is the same for all architectures and I want to keep the article clean. You just have to adjust this article to your platform.
So, what's with the size of the structure?
You should know that members of data structure(represented by struct keyword in c) are aligned to the power of 2. Each element is stored in the closest(next) address with the appropriate alignment. The whole structure should be aligned as aligned its member with the longest alignment.
The type of each member of the structure usually has a default alignment(if you are not using #pragma pack directive). It's 1 byte for char, 2 bytes for short, 4 bytes for int. You should check this table for your arch.
So the structure
struct { char a; short b; int c; } data;should be 8 bytes long. How is it calculated? The structure has one char, one short and one int members. The alignment should look like
+-----------------------------------+ |char| XX | short | int | +-----------------------------------+ 0 2 4 8The short member is stored on the distance of 2 bytes from the address of char because the alignment of short is 2 bytes, the int member is stored just after the short, because the address from the beginning(in this case, or in general from the previously aligned members) is suitable for alignment of int.
But if you change the sequence of the members the whole picture could change, though the number of members and their sizes didn't change. The structure
struct { char a; int c; short b; } data;on the same platform should be 12 bytes long. Why? Let's calculate.
+---------------------------------------------+ |char| XX | XX | XX | int | short | +---------------------------------------------+ 0 2 4 8 12That's because the address of integer member is adjusted to its alignment.
Knowing these rules you can optimize the sizes of the structures just moving position of the members inside the structure. Let's add one char in the end to the previously declared structure:
struct { char a; short b; int c; char d; } data;The size of the structure is 12. It's easy to calculate. The size of the structure should be as aligned its member with the longest alignment. In this case the longest alignment is 4. Sequence of char, short, int is aligned to 8 bytes. Adding one char to the end you force compiler to align the structure to 12 bytes, it can't be 9 or anything else. If you look at the alignment of the original structure you could see unused byte that appeared because of the alignment. Let's move d just after(or before, doesn't matter) the a structure member:
struct { char a; char d; short b; int c; } data;The size of this structure should be 8 bytes.
+-----------------------------------+ |char|char| short | int | +-----------------------------------+ 0 2 4 8If you deal with embed devices where you have significantly small amount of memory it's good optimization. 8 bytes vs. 12 bytes, or 1K vs. 1.5K in case of 128 copies of the structure.
Another approach which is also platform and compiler dependent is to use #pragma pack directive. In general structure
struct { int c; short b; } data;should be 8 bytes long. But if you use #pragma pack with alignment to 2 bytes you may force the whole structure will be aligned to 2 bytes.
#pragma pack(push) #pragma pack(2) struct { int c; short b; } data; #pragma pack(pop)This structure should be 6 bytes long.
The alignment can cause troubles especially if the data is transmitted between different platforms where alignment or size of type may differ. If it's possible strings(sequences of bytes/chars) should be used. Their alignment should always be 1 byte long.