为什么这个结构不能正确对齐?

时间:2014-11-25 12:56:14

标签: c gcc struct sizeof memory-alignment

我正在读这个答案:C struct memory layout?并且很想知道原因:

struct ST
{
   long long ll;
   char ch2;
   char ch1;
   short s;
   int i;
};

仍然是24字节而不是16字节的大小。我期待2 * char + short + int以适应8个字节。为什么会这样?

修改

很抱歉这个混乱,我正在使用64位系统(debian) gcc(Debian 4.4.5-8)4.4.5 。由于填充,我已经知道它了。我的问题是为什么?其中一个答案表明:

char = 1 byte
char = 1 byte
short = 1 byte (why is this 1 and not 2?)
* padding of 5 bytes

我的问题是,为什么这里的填充...为什么不在短路后直接放置 int ,它仍然适合8个字节。

3 个答案:

答案 0 :(得分:1)

关于填充的全部内容。在visual studio(以及其他一些编译器)中,您可以使用#pragma push / pack使其按照您的意愿进行对齐。

#pragma pack(push, 1)
struct ST
{
   /*0x00*/ long long ll;
   /*0x08*/ char ch2;
   /*0x09*/ char ch1;
   /*0x0a*/ short s;
   /*0x0c*/ int i;
   /*0x10*/
};
#pragma pack(pop)

既然你说它的大小是24,那么我猜测编译器会通过这样的方式将你对齐4个字节:

struct ST
{
   /*0x00*/ long long ll;
   /*0x08*/ char ch2;
   /*0x09*/ char padding1[0x3];
   /*0x0c*/ char ch1;
   /*0x0d*/ char padding2[0x3];
   /*0x10*/ short s;
   /*0x11*/ char padding3[0x2];
   /*0x14*/ int i;
   /*0x18*/
};

(对不起,我想在做这种事情的时候是十六进制.0x10是十进制的16,0x18是十进制的24。)

答案 1 :(得分:1)

简单的答案是:它不是24个字节。或者您正在使用我无法找到ABI文档的64位s390 Linux端口上运行。 Debian可以运行的每个其他64位硬件的结构大小为16字节。

我已经为一堆不同的CPU ABI挖出了ABI文档,它们或多或少都有这样的措辞(似乎它们都是相互复制的):

  

结构和联合体假定其最严格对齐的组件对齐。每个成员都被分配到具有适当对齐的最低可用偏移量。任何对象的大小始终是对象对齐的倍数。

我发现的所有架构ABI文档(mips64,ppc64,amd64,ia64,sparc64,arm64)都具有char 1,short 2,int 4和long long 8的对齐方式。

尽管允许操作系统制作自己的ABI,但几乎每个类Unix系统,特别是Linux都遵循System V ABI及其补充CPU文档,这些文档很好地指定了这种行为。并且Debian肯定不会改变这种行为,使其与所有其他Linux不同。

这是一个快速验证(全部在amd64 / x86_64上,这是您最有可能运行的):

$ cat > foo.c
#include <stdio.h>

int
main(int argc, char **argv)
{
    struct {
        long long ll;
        char ch2;
        char ch1;
        short s;
        int i;
    } foo;

    printf("%d\n", (int)sizeof(foo));
    return 0;
}

的MacOS:

$ cc -o foo foo.c && ./foo && uname -ms
16
Darwin x86_64

Ubuntu的:

$ cc -o foo foo.c && ./foo && uname -ms
16
Linux x86_64

CentOS的:

$ cc -o foo foo.c && ./foo && uname -ms
16
Linux x86_64

OpenBSD的:

$ cc -o foo foo.c && ./foo && uname -ms
16
OpenBSD amd64

您的编辑还有其他问题。或者那不是您正在测试的结构,或者您正在一个非常奇怪的硬件架构上运行并将其指定为&#34; 64位&#34;相当于说&#34;我驾驶这种政府发行的车辆,它有非常奇怪的加速度,发动机在5分钟后切断了#34;并没有提到你在谈论航天飞机。

答案 2 :(得分:0)

通常为了最小化填充,通常的做法是从大到小对成员进行排序,您是否可以尝试对它们进行重新排序并查看其中的内容?

struct ST
{
   long long ll;  //8 bytes
   int i;         //4bytes
   short s;       //2 bytes
   char ch2;      //1 byte
   char ch1;      //1 byte
};

总计是16个字节