繁体   English   中英

32位和64位架构上的c中的结构填充之间有何区别?

[英]what is difference between structure padding in c on 32bit and 64bit architecture?

我从http://fresh2refresh.com/c-programming/c-structure-padding/读取了内存,以32位处理器中的4个字节和64位处理器中的8个字节为一组,但没有弄清楚之间的区别这两个。

struct structure2 
    {
           int id1;
           char name;
           int id2;
           char c;
           float percentage;                      
    };

通过32位处理器(更具体地说,它是在谈论数据总线的大小而不是寄存器的大小),这意味着一次将读取和处理32位(4字节)的数据。

现在,考虑一个int:

int a=10; //assuming 4 bytes

00000000 000000000 00000000 00001010

假设没有端序架构,则将其存储为:

------------------------------------------------------------------------
| 00001010  |  00000000  |  00000000   |  00000000   |  <something_else>   
-------------------------------------------------------------------------
  1st byte     2nd byte     3rd byte      4th byte
\--------------------------------------------------/
                         |
               4 bytes processed together

在这种情况下,当处理器将读取要处理的数据时,它可以一次性处理整个整数(所有4个字节在一起)(更严格地说,在1个机器周期内)

但是,请考虑以下情况:存储了相同的整数,

------------------------------------------------------------------------
|<something_else>| 00001010  |  00000000  |  00000000   |  00000000   |     
-------------------------------------------------------------------------
  1st byte     2nd byte     3rd byte      4th byte
\------------------------------------------------------/
                         |
               4 bytes processed together

在这种情况下,处理器将需要2个机器周期来读取整数。


大多数体系结构始终尝试最小化CPU周期。 因此,内存中的第一种排列被许多编译器所青睐,因此会强制执行对齐要求(填充)。 因此,将4个字节的int存储在以4s的倍数开头的地址中,将chars存储为1s的倍数,将8个字节的doubles存储为8s的倍数,将8个字节long long int存储为8s的倍数,依此类推...

现在考虑你的结构

struct structure2 
{
       int id1;   //assuming 4 byte int
       char name;  // 1byte
       int id2;    //4 byte
       char c;     // 1 byte
       float percentage;    //assuming 4 byte float                  
};

id1将存储在内存中的某个地址(以4的倍数开头)中,并占用4个字节。

名称将占用下一个字节。

现在,如果将id2存储在下一个字节中,则会破坏上面的对齐规则。 因此,它将保留3字节的填充并以adress开始存储,该地址是4的下一个倍数,将占用4字节。

对于c来说 ,同样的事情与name相同。 它占用下一个1字节,并保留3字节的填充。

最后百分比存储在接下来的4个字节中。

因此,结构的总大小变为20个字节


可以说一个更复杂的情况

struct mystructure
{
   char        a; //1 byte char
   double      b; // 8 byte double
   int         c; // 4 byte int
}

乍一看,这里的大小可能是20字节 (char为1字节+ 7字节为填充+ 8字节为double + 4字节为int)。

但是实际大小为24个字节

假设有人声明了此结构的数组

struct mystructre arr[4];

尽管arr [0]正确对齐,但此处(假定为20字节结构),但是如果仔细检查,会发现arr [1] .b未对齐。 因此,在结构的末尾添加4个字节的额外填充以使结构大小为其对齐方式的倍数。(每个结构也都有其自己的对齐要求)。

因此,总大小为24个字节。


整数,长整数等的大小由编译器决定。 编译器通常会处理处理器体系结构,但可能会选择不这样做。

同样,是否使用填充由编译器决定。 不填充称为打包 一些编译器具有允许打包的显式选项。

在GCC(GNU C编译器)中,您可以使用__attribute__((__packed__))做到这一点,因此在以下代码中

struct __attribute__((__packed__)) mystructure2 
{
 char a;
 int b;
 char c;
};

由于明确请求打包结构, mystructure2的大小为6个字节。 此结构将较慢处理


您现在可以自己弄清楚,在64位处理器中会发生什么,或者int的大小是否不同。

该网站并没有精确地确定使用哪种64位平台,但是似乎假定使用长度对齐的整数的ILP64( intlong和指针为64位)平台。 这意味着int在32位处理器上为4个字节,在64位处理器上为8个字节,并且每个字节必须以其自身长度的倍数对齐。

结果是nameid2之间的填充长度发生了变化(保留id2的对齐所必需的填充)。

在32位平台上,将有3个字节的填充。 在64位平台上,将有七个。

cpercentage之间的填充很可能不会更改,因为浮点变量的大小不受处理器位的影响。

暂无
暂无

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

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