struct的大小和相应的变量

时间:2009-10-08 17:06:36

标签: c

如果我定义一个char变量

char a;

和具有单个char成员的结构

struct OneChar {
char a;
};

这两个定义在所有编译器中的大小都是'char'吗? 我怀疑的是,如果我们在结构中定义一个char变量,由于内存打包它会比char的大小更大吗?

6 个答案:

答案 0 :(得分:6)

这取决于架构和编译器。对于这种特殊情况,您应该是安全的,但请查看Data Structure Padding

这是excerpt

  

x86上C结构的典型对齐

     

存储数据结构成员   按顺序存储在内存中   成员Data1下面的结构   将始终位于Data2和Data2之前   将始终位于Data3之前:

struct MyData
{
    short Data1;
    short Data2;
    short Data3;
};
     

如果“短”类型存储在两个中   然后每个成员的内存字节   上面描述的数据结构   将是2字节对齐。 Data1会   偏移量为0,偏移量为2的数据2和   偏移量为4的Data3。大小   结构将是6个字节。

     

每个成员的类型   结构通常有默认值   对齐,意思是它会,   除非另有要求   程序员,对齐   预先确定的边界。下列   典型的比对有效   来自Microsoft,Borland和。的编译器   编译32位x86时的GNU:

     
      
  • char(一个字节)将以1字节对齐。
  •   
  • 短(两个字节)将是2字节对齐。
  •   
  • int(四个字节)将是4字节对齐。
  •   
  • 一个浮点数(四个字节)将是4字节对齐的。
  •   
  • 双重(8字节)将在Windows上对齐8字节,在Linux上对齐4字节。
  •   
     

这是一个成员的结构   各种类型,总共8个字节   汇编

struct MixedData
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;
};
     

编译后的数据结构   将补充填充   字节以确保正确对齐   每个成员:

struct MixedData  /* after compilation */
{
    char Data1;
    char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */
    short Data2;
    int Data3;  
    char Data4;
    char Padding1[3];
};
     

结构的编译大小是   现在12个字节。重要的是要注意   用最后一个成员填充   所需的字节数   符合最大的类型   结构体。在这种情况下,3个字节   添加到最后一个成员来填补   结构到长字的大小。

     

可以更改对齐方式   减少记忆的结构   他们需要(或符合   现有格式)通过改变   编译器的对齐(或“打包”)   结构成员。

     

请求MixedData   上面的结构与一个结构对齐   字节边界将具有编译器   丢弃预先确定的对齐   的成员和没有填充字节   会被插入。

     

虽然没有标准的方法   定义结构的对齐   成员,一些编译器使用#pragma   指定内部包装的指令   源文件。这是一个例子:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */

struct MyPackedData
{
    char Data1;
    long Data2;
    char Data3;
};

#pragma pack(pop)   /* restore original alignment from stack */
     

这个结构会有编译   大小为6个字节。以上指令   可以在编译器中找到   微软,Borland,GNU等等   其他

答案 1 :(得分:1)

只要有一个成员,我认为你的假设是安全的。

答案 2 :(得分:1)

您列出的案例将在我知道的所有ABI下打包为1字节结构。

但是如果你需要移植处理更复杂的情况,最佳做法是在计算内存大小时始终使用sizeof(struct OneChar),并在需要通过如下技巧计算地址时获取字段地址的偏移量: / p>

(char*)&(((struct OneChar*)0)->a) - (char*)0

答案 3 :(得分:0)

所有a s都具有相同的大小,无论它们是独立的还是在结构内。

结构内部可能发生的是成员之间存在填充......但这也可能发生在“独立”变量中。

答案 4 :(得分:0)

当你获取结构的大小时,它包含填充字节。但是,如果您有以下内容:

void fun()
{
    char c;
    int n;
}

编译器可以根据它看到的任何原因自由插入填充。因此,在独立变量的情况下,填充可能就在那里,你只是在结构的情况下无法知道它。

答案 5 :(得分:0)

各种编译器将优化以在结构之间或结尾处添加填充。因此,在所有编译器或平台上假设分配的大小看起来并不安全。检查编译器选项以设置struct padding。

例如,Visual Studio使用#pragma pack指令覆盖默认优化。