在上下文及头文件均正常的情况下,以下代码打印的结果是(假设运行在 64 位计算机上):

struct st_t {
    int status;
    short *pdata;
    char errstr[32]; 
};
st_t st[16];
char *p = (char *)(st[2].errstr + 32);
printf("%d", (p - (char *)(st)));

A. 32 B. 120 C. 114 D. 144

结构体对齐:

  • 内部对齐:结构体成员之间会留有空隙。
  • 外部对齐:在结构体数组中,结构体之间也可能留有空隙。

对齐规则:

1.第一个成员在与结构体变量偏移量为0的地址

2.其他成员变量要对齐到对齐数的整数倍的地址处(对齐数 = 编译器默认的对齐数(VS中为8) 与 成员变量大小的较小值),即 内部对齐

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数,取所以成员变量中对齐数最大的)的整数倍外部对齐

4. 如果嵌套结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包含嵌套结构体的对齐数)的整数倍,如下:

struct S3 {
	double d;  //▣
	char c;    //▤
	int i;     //▦
};
               //s3内存布局:▣▣▣▣▣▣▣▣▤▢▢▢▦▦▦▦  最大对齐数为8
                            ↑          ↑     ↑
struct S4 {                 0          8     12
	int f;     //▦
	char c;    //▤
	struct S3 s3;  
};             //s4内存布局:▦▦▦▦▤▢▢▢▣▣▣▣▣▣▣▣▤▢▢▢▦▦▦▦
                            ↑     ↑    ↑    
                            0     4    8

为什么要结构体对齐?

  • 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问

如何使结构体内存尽可能小?

根据成员的大小按从大到小的顺序依次声明即可,如double声明在int前,而int声明在char前

修改默认对齐数:

#pragma pack(x)//设置默认对齐数为x
如果不想对齐,直接声明 #pragma pack(1)

文章作者: 极简
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 后端技术分享
C/C++
喜欢就支持一下吧