Structure Fill

I know there is an addition to the structure ( from this post )

struct A -->8 bytes { char c; char d; //2 padding here int i; }; struct B -->12 bytes { char c; //3 padding here int i; char d; //3 padding here }; 

Now I do not understand the following example:

  typedef struct { -->**shouldn't it be 12 bytes** int a; char *str; } TestS; TestS s; int main(int argc, char *argv[]) { printf("An int is %lu bytes\n", sizeof( int )); -->4 printf("A Char * is %lu bytes\n", sizeof( char *)); -->8 printf("A double is %lu bytes\n", sizeof( double )); -->8 printf("A struct is %lu bytes\n", sizeof s); -->why 16? return 0; } 

At first I thought it could be compatible with 8 * N bytes (for using ubuntu-64 ), so I'm trying to create more structures.

  typedef struct { int i; char *str; } stru_12; typedef struct { int i; char *str; char c; } stru_13; typedef struct { int i; char str[7]; } stru_11; typedef struct { char *str; double d; } stru_16; stru_12 test12; stru_13 test13; stru_11 test11; stru_16 test16; int main (int argc, char *argv[]) { printf("A test12 is %lu bytes, address is %p\n", sizeof test12, &test12); printf("A test13 is %lu bytes, address is %p\n", sizeof test13, &test13); printf("A test11 is %lu bytes, address is %p\n", sizeof test11, &test11); printf("A test16 is %lu bytes, address is %p\n", sizeof test16, &test16); } 

Result:

Test 12 is 16 bytes, address 0x601060

A test13 - 24 bytes, address - 0x601090

Test11 is 12 bytes, address is 0x601080

Test 16 - 16 bytes, address - 0x601070

Too bad it took so long.

My question is:

  • Why is test12 (int + char *) equal to 16 bytes and test13 (int + char * + char) equal to 24? (it seems that 8 * N , but 12 bytes are allowed)

  • Why do differences in structure addresses amount to 16 addressing units (more additions?)?

For use:

cache_alignment: 64

address sizes: 36 bits physical, 48 bits virtual

Ubuntu 14.04.1 LTS x86_64

+7
c struct
source share
2 answers

The second question is implementation (and this is actually the first, but I will show you why you get the gap that you get independently). Your platform is apparently 64-bit, and therefore your data pointers are also (64-bit). In doing so, we look into structures.


stru_12

 typedef struct { int i; char *str; } stru_12; 

This is aligned, so str always gets to an 8-byte boundary, including in a continuous sequence (array). To do this, 4 bytes of padding are entered between i and str .

 0x0000 i - length=4 0x0004 pad - length=4 0x0008 ptr - length=8 ====================== Total 16 

An array of them will always have ptr at the 8-byte boundary if the array starts with the same one (which it will be). Since adding padding between i and str also caused the structure to be a multiple of 8, no extra padding is required outside of this.


stru_13

Now let's see how this is achieved using this:

 typedef struct { int i; char *str; char c; } stru_13; 

The same addition will be used between i and str to place str once on the 8-byte boundary, but adding c complicates the situation. To achieve the goal of pointers that are always at 8-byte boundaries (including the sequence / array of these structures), the structure requires filling the tail, but how much? Well, I hope that obviously the total size of the structure should be a multiple of 8 to ensure that any built-in pointers (which are also a multiple of 8) are correctly aligned. In this case, seven bytes of tail padding are added to bring the size to 24 bytes:

 0x0000 i - length=4 0x0004 pad - length=4 0x0008 ptr - length=8 0x0010 c - length=1 0x0011 pad - length=7 ====================== Total 24 

stru_13 (part of deux)

So try this one. What would you think that the same fields that we had before, but ordered differently, would lead to:

 typedef struct { char *str; int i; char c; } stru_13; 

Well, we know that we want str on an 8-byte border and i on a 4-byte border, and, frankly, about it c (always the bride) p>

 0x0000 ptr - length=8 0x0008 i - length=4 0x000c c - length=1 0x000d pad - length=3 ====================== Total 16 

Run this, although your test program, and you will see that it is laid out, as we said above. It reduces to 16 bytes. All we did was change the order to a more space-friendly layout that still supports our requirements, and we reduced the default representation by 8 bytes (one third of the original structure with the previous layout). To say that it is important to take away from everyone would be an understatement.

+4
source share

Pointers must be properly aligned for CPU usage.

In C / C ++, structures should work in arrays, so the end of the structure is complemented in this regard.

 struct A { char a; // 7 bytes of padding char *p; char b; // 7 bytes of padding }; A array[3]; // the last padding is important to do this 

In such a structure, p must be aligned so that the processor can read the pointer without generating an error (32-bit INTEL processors can be configured without errors on unbalanced data, but this is not a good idea: it is slower and it often skips errors that are errors. 64-bit processors have more limitations in this arena.)

So, since you are at 64 bits, the pointer has 8 bytes, and the alignment before the pointer must be a multiple of 8.

Similarly, the total size of the structure must be a multiple of the largest type in the structure, here it is 8, so it fits in the next 8 bytes.

There are really only 2 cases where you should worry about this: (1) creating a structure that will be saved in a file, and (2) creating a structure that you select in very large quantities. In all other cases, do not worry about it.

+3
source share

All Articles