首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C-强制使用_Alignas说明符对齐-为什么使用内存填充?

C-强制使用_Alignas说明符对齐-为什么使用内存填充?
EN

Stack Overflow用户
提问于 2018-05-09 16:11:09
回答 1查看 90关注 0票数 0

关于C语言中的内存对齐,以及在使用_Alignas说明符强制将变量对齐到一定字节数后如何分配内存,我有几个问题。

此代码在输出中显示每个已声明变量的内存地址:

代码语言:javascript
复制
#include <stdio.h>

int main(void)
{
       unsigned char dx = 1;
       unsigned char ca  = 1;
       unsigned char cx  = 1;
       unsigned char dz = 1;
       unsigned char cb = 1;
       unsigned char _Alignas(double)  cz = 1;

       char * p_begin = (char *) &cz;
       char * p_end = (char * ) &dx + sizeof(dx);

       printf("Addresses   Value\n");
       for (char * p = p_begin; p < p_end; p++)
       {
              printf("%9p   %6X", p, 0xff & *p);

              if (p == (char *) & dx) printf(" <- dx\n");
              else if (p == (char *) & ca) printf(" <- ca\n");
              else if (p == (char *) & cx) printf(" <- cx\n");
              else if (p == (char *) & dz) printf(" <- dz\n");
              else if (p == (char *) & cb) printf(" <- cb\n");
              else if (p == (char *) & cz) printf(" <- cz\n");
              else printf("\n");
       }

       return 0;
}

在我的电脑上,输出如下:

代码语言:javascript
复制
Addresses   Value
   28ff08        1 <- cz
   28ff09       FF
   28ff0a       28
   28ff0b        0
   28ff0c       CE
   28ff0d       2A
   28ff0e       40
   28ff0f        1 <- cb
   28ff10        1 <- dz
   28ff11        1 <- cx
   28ff12        1 <- ca
   28ff13        1 <- dx

Process returned 0 (0x0)   execution time : 0.016 s
Press any key to continue.

在强制cz变量对齐8字节后,我期望看到的唯一行为是cz被分配给一个值是8的倍数的地址,我不希望看到从填充中跟随cz。为什么会有这样的行为?我还预计与填充相对应的字节数加上1字节的数据大小会得到8个字节,而填充占用6个字节,原因是什么?

EN

回答 1

Stack Overflow用户

发布于 2018-05-09 20:10:45

堆栈通常向下增长。这没有本质的原因,很大程度上是历史发展的结果。为堆栈分配一个内存区域,将堆栈指针设置为指向堆栈的高端,并启动程序的主例程。因为程序需要更多的堆栈空间,所以它减少了堆栈指针。

在您的示例中似乎发生的情况是,编译器按照遇到对象的顺序为对象分配空间。首先看到的是dx,因此会为它分配堆栈上的下一个可用空间0x28ff13。然后看到ca,并将其分配给0x28ff12。我们看到,随着堆栈的增长,它从较高的地址(开始的地址)到较低的地址。

当编译器到达您请求的8字节对齐的cz时,编译器跳转到下一个8的倍数(仍然是向下的方向),即0x28ff08

当然,编译器可以考虑整个情况(而不是一次只查看一个对象),并将cz放在0x28ff10处,然后将其他对象放在它周围,从而使用更少的堆栈空间。如果在启用优化的情况下编译,编译器可能会这样做。另一方面,编译器可能要求在您的平台上保持堆栈指针对齐到8个字节(或更多),因此重新排列这些特定对象无论如何都不会节省任何堆栈空间。

在C标准中没有关于这方面的规则。编译器可以随心所欲地安排它的堆栈。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50248513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档