c++ 为什么对于一个有1个成员(char)的结构,在堆栈上的对齐处理方式与该成员直接在堆栈上时不同?

jecbmhm3  于 2023-05-24  发布在  其他
关注(0)|答案(1)|浏览(123)

我在www.example.com上运行了一个实验cpp.sh(没有特殊标志),其中单词大小似乎是4字节。在我的实验中,我在堆栈上初始化了两个Data类型的元素,一个只有一个char的结构,并打印出它们的地址。我对两个char类型的变量做了同样的操作。

#include <iostream>
#include <bitset>

struct Data {
    char c;    
};

void PrintAddr(const void* ptr) {
    std::cout << std::bitset<32>((unsigned int) ptr) << std::endl;
}

int main()
{
    std::cout << "word size = " << sizeof(size_t) << std::endl;
    std::cout << "sizeof = " << sizeof(Data) << std::endl;
    std::cout << "alignof = " << alignof(Data) << std::endl;
    
    std::cout << "Data addresses: " << std::endl;

    Data a, b;
    PrintAddr(&a);
    PrintAddr(&b);
 
    std::cout << "char addresses: " << std::endl;
 
    char c, d;
    PrintAddr(&c);
    PrintAddr(&d);
}

输出:

word size = 4
sizeof = 1
alignof = 1
Data addresses: 
00000000010100000101001011101000
00000000010100000101001011100000
char addresses: 
00000000010100000101001011011111
00000000010100000101001011011110

看起来像是为数据类型的变量a和b添加了填充,而没有为类型c和d添加任何填充。为什么会这样呢?

cvxl0en2

cvxl0en21#

一个迂腐的答案可能是, C++ 规范没有保证局部变量的地址可能是什么。它们可能紧挨着,或者可能有填充物,或者它们可能完全不相关!一个语言律师可能会很高兴地离开它。
如果你问为什么一个特定的编译器会这样做,你可以修改你的问题(或添加标签)来指定它。
请注意,这些自动变量可能甚至没有地址,直到您实际获取它们的地址-它们只是存在于寄存器中。对于char变量可能更是如此。
所以这是我的猜测-你使用的编译器很乐意将自动char变量打包到堆栈上(当你获取它们的地址时),但不愿意以同样的方式打包自动struct变量。

相关问题