32位和64位架构的c结构填充有什么区别?

时间:2016-09-16 09:07:03

标签: c padding cpu-architecture

我读到内存被安排为32位处理器中的4个字节组和来自http://fresh2refresh.com/c-programming/c-structure-padding/的64位处理器中的8个字节,但没有说明这两者之间的区别。

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

2 个答案:

答案 0 :(得分:2)

通过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存储在从4的倍数开始的地址中,chars存储在1的多个中,8个字节doubles存储在8个的多个中,8个字节{{1多个8s等等......

现在考虑一下你的结构

long long int

id1 将存储在内存中的某个地址(从4开始),占用4个字节。

名称将占用下一个字节。

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

对于 c ,同样的事情发生在 name 上。接下来需要1个字节并保留3个字节的填充。

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

所以结构的总大小变为 20字节

更复杂的案例会说

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                  
};

这里可能乍一看说大小将 20个字节(char为1个字节+ 7个字节填充+ 0个字节用于double + 4个字节用于int)。

但实际大小为 24字节

说某人声明了这个结构的数组

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

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

因此总大小为24字节。

整数的大小,长整数等由编译器决定。编译器通常负责处理器体系结构,但可以选择不使用。

类似地,是否使用填充是由编译器决定的。不填充称为包装。有些编译器有明确的选择允许打包。

在GCC(GNU C编译器)中,您可以使用struct mystructre arr[4]; 执行此操作,因此在以下代码中

__attribute__((__packed__))

mystructure2的大小为6个字节,因为显式请求打包结构。此结构处理速度

你现在可能已经想到了,64位处理器会发生什么,或者int的大小是不同的。

答案 1 :(得分:0)

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

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

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

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