简体   繁体   English

为什么sizeof()在64位cpu上有所不同?

[英]Why sizeof() differs on 64bit cpu?

Consider following example: 考虑以下示例:

#include <stdio.h>
#include <inttypes.h>

struct A {
        uint32_t i1;
        uint32_t i2;
        uint32_t i3;
        uint64_t i4;
        uint32_t i5;
        uint32_t i6;
        uint32_t i7;
        uint64_t i8;
        uint32_t i9;
};

struct B {
        uint32_t i1;
        uint32_t i2;
        uint32_t i3;
        uint32_t i4;
        uint32_t i5;
        uint32_t i6;
        uint32_t i7;
        uint64_t i8;
        uint64_t i9;
};

int
main()
{
        struct A a;
        struct B b;

        printf("sizeof(a) = %u, sizeof(b) = %u\n", sizeof(a), sizeof(b));

        return 0;
}

Output is: 输出是:

$ ./t2 
sizeof(a) = 56, sizeof(b) = 48
$ 

Why are they differ on 64bit machine ? 他们为什么在64位机器上有所不同? On 32 bit platform results are the same: 在32位平台上的结果是相同的:

$ ./t2
sizeof(a) = 44, sizeof(b) = 44

Some diagrams to help you see: 一些图表可以帮助您了解:

32-bit: 32位:

+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 |   i4    | i5 | i6 | i7 |   i8    | i9 | Struct A
+----+----+----+----+----+----+----+----+----+----+----+

+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 |   i8    |   i9    | Struct B
+----+----+----+----+----+----+----+----+----+----+----+

64-bit: 64位:

+---------+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 |~~~~|    i4   | i5 | i6 | i7 |~~~~|   i8    | i9 |~~~~| Struct A
+---------+---------+---------+---------+---------+---------+---------+

+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 |~~~~|   i8    |   i9    | Struct B
+---------+---------+---------+---------+---------+---------+
  • + : address boundaries + :地址边界
  • ~ : padding :填充

The compiler aligns the struct members by a boundary (which is different in your compilation attempts). 编译器通过边界(在编译尝试中不同)对齐struct成员。

Add a 添加一个

#pragma pack (1)

directive at the beginning of source file and retry. 指令在源文件的开头并重试。

Because it can. 因为它可以。 The compiler isn't required to use the same layout between 32 and 64-bit mode. 编译器不需要在32位和64位模式之间使用相同的布局。 It can insert padding when it wants to. 它可以在需要时插入填充。 You shouldn't rely on the precise layout of the struct in the first place. 您不应该首先依赖结构的精确布局。

In principle, it could even change the padding each time you compile. 原则上,它甚至可以在每次编译时更改填充。 (It's hard to imagine why the compiler would do this, but it's allowed to) (很难想象为什么编译器会这样做,但它被允许)

64-bit integers have to be placed on a 64-bit memory boundary. 必须将64位整数放在64位存储器边界上。 Thus, when creating a struct A on a 64-bit machine, the compiler sticks a 4-byte padding space after i3 and i7 - thus putting an extra 8 bytes in there. 因此,当在64位机器上创建结构A时,编译器在i3和i7之后粘贴一个4字节的填充空间 - 因此在那里增加了8个字节。

由于元素之间的填充。

This is caused due to structure aligning: struct A has 3 32 bit values followed by a 64bit one. 这是由于结构对齐引起的: struct A有3个32位值,后跟64位值。 Regardless of the packing of the first 3 elements the 64bit element definitely won't start between boundaries (ie taking up half of two separate 64bit values) on 64bit, so there is at least a 32bit padding between the 3rd and 4th element. 无论前3个元素的打包如何,64位元素肯定不会在64位之间的边界之间开始(即占据两个独立的64位值的一半),因此在第3和第4个元素之间至少有32位填充。

sizeof(b)是48,因为最后一个uint32占用了一个完整的64位(因为后续的uint64s与64位块对齐.sizeof(a)占用更多因为前3个unit32s占用2个块,接下来的3个占用2个块,最后的uint32占用一个完整的64位块

This is because of aligning. 这是因为对齐。

It is possible that 64bit integers on your platform are required to be 64bit aligned. 您的平台上的64位整数可能需要64位对齐。

So In the mixed structure you have 3 32 bit integer, after them there must be inserted an other 32bit padding to have the 64bit integer correctly aligned. 所以在混合结构中你有3个32位整数,在它们之后必须插入另一个32位填充以使64位整数正确对齐。

The size difference should vanish if you insert and even number of 32bit field before your 64 bit field. 如果在64位字段之前插入偶数32位字段,则大小差异应该消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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