简体   繁体   中英

64-bit compiler struct padding with 32-bit arguments

I've been trying to understand how 64-bit compiler enforces struct alignment, and I can't understand why there is no padding in case a struct has only 32-bit arguments.

I would expect to have padding even in that case as 64-bit CPUs access memory using 64-bit pointers, don't they?

   typedef struct {
       uint32_t a1;
       uint32_t a2;
       uint32_t a3;
   }tHeader;

  typedef struct{
      tHeader header;
      uint32_t data1;
      uint32_t data2;
  }tPacket1;



0               7   bytes
+-------+-------+
|  a1      a2   |
+-------+-------+
+-------+-------+
|  a3     data1 |       
+-------+-------+
+-------+-------+
| data2         |      <---- Why no padding here?
+-------+-------+
20 bytes.

Padding example when 64-bit argument is present:

   typedef struct {
       uint32_t a1;
       uint32_t a2;
       uint32_t a3;
       uint64_t a4;
   }tHeader;

  typedef struct{
      tHeader header;
      uint32_t data;
  }tPacket1;



0               7   bytes
+-------+-------+
|  a1      a2   |
+-------+-------+
+-------+-------+
|  a3    PADDING|       
+-------+-------+
+-------+-------+
|       a4      |
+-------+-------+
+-------+-------+
| data   PADDING|       <---- Why padding here?
+-------+-------+
Total: 8 * 4 = 32 bytes.

Tested with:

$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

No padding is needed in the first case because all the members have 4-byte alignment. So if you have two consecutive structures, it can be laid out like:

0               7   bytes
+-------+-------+
|  a1      a2   |
+-------+-------+
+-------+-------+
|  a3     data1 |       
+-------+-------+
+-------+-------+
| data2    a1   |
+-------+-------+
+-------+-------+
|  a2      a3   |
+-------+-------+
+-------+-------+
| data1   data2 |       
+-------+-------+

But that won't work in the second example because a4 needs 8-byte alignment. If it omitted the padding at the end, you'd have this:

0               7   bytes
+-------+-------+
|  a1      a2   |
+-------+-------+
+-------+-------+
|  a3    PADDING|       
+-------+-------+
+-------+-------+
|       a4      |
+-------+-------+
+-------+-------+
| data     a1|      
+-------+-------+
+-------+-------+
|  a2      a3   |
+-------+-------+
+-------+-------+
|PADDING   a4   |       
+-------+-------+
+-------+-------+
| a4      data  |
+-------+-------+

But splitting the second a4 like that is not permitted.

You could use the packed attribute to force it. Then the 64-bit element would be accessed using multiple 32-bit instructions. This would also obviate the padding between a3 and a4 .

The idea of padding is to optimize the accesses and not capricious. 64bit cpus can make 64bit memory bus accesses , but there's no benefit of making a 64bit access when the bus transfer is done for a 32 bit quantity. When the cpu wants to transfer a 32bit quantity, it selects a 64bit address to select the 64bit register, and only reads the bytes corresponding to the quantity you selected. The compiler pads a structure, when you have a 64bit field that is not at a multiple of 8 address. In case you have to access it, the cpu should have to make two 64bit accesses to load/store the data if the data is not aligned to a multiple of 8 address. For this reason is done alignment. In case you have a structure that has only 32 bit addresses, accessing those registers only requires 32 bit bus accesses, so only 32bit alignment is required for the whole structure.

Let's go to the extreme... imagine you have a char register. Should you do a 64bit bus access and require the char to be aligned to a 64bit address to transfer only one byte of data?

In order to calculate alignment you have to think:

  • What is the offset of free space i got from the last field in the structure?
  • What is the alignment required by the next field?

Let's assume the last field packed in the structure left an offset of 13 bytes (you used a char[13] type) and imagine that the next field to pack is a char : A char requires one byte, so it can be appended to the last field without any alignment (it has alignment of one). Now assume it is a short (two bytes), the compiler should put it in the next even address (offset 14, with one byte of padding, and this will allow the structure to require an even address to be aligned (or the short field would not be aligned) In case it is a 32bit int , then the offset for the next field would require a multiple of 4 address, and 3 bytes of padding should be inserted, and so the offset should be at 16, with a 4byte alignment requirement for the whole structure. In case the data is a 64bit integer, the offset should have been fixed at an 8 byte boundary, making the compiler to insert 3 bytes of padding to make it at offset 16, and the alignment requirement for the whole structure would be 16 bytes. When no more fields are left to complete the structure, there's still some padding to make the whole structure to fit an integer number of bytes equal to the next multiple of the required alignment of the structure, so in case you append two structures, as in an array of structures of this type, the alignment is conserved. So in case we add at the end of the structure proposed a final 3 char array, we'll need to add a pad byte to fill the 4byte alignment of the whole structure.

So, once said this, the padding is computed based on the alignment requirements of the next field, based on the alignment required by the field (if it is an array the alignment required is the same as for the individual cell type of the array, and if it is a simple type it is the size of the type itself, and for structures the base type should be the alignment requirements of the next field with the biggest alignment requirements of the structure)

In the case you shown, only 32bit integers are included, so no padding is used between them (if the structue is aligned to 32bit, all fields will be aligned to 32bit) and no padding is needed on the end of the structure (to maintain the alignment in case of an array of structures)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM