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

3 c++ x86 padding clang memory-alignment

我在 cpp.sh 上进行了一个实验(没有特殊标志),其中字大小似乎是 4 个字节。在我的实验中,我在堆栈上初始化了两个 type 元素Data,一个只有一个字符的结构,并打印出它们的地址。我对两个 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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

word size = 4
sizeof = 1
alignof = 1
Data addresses: 
00000000010100000101001011101000
00000000010100000101001011100000
char addresses: 
00000000010100000101001011011111
00000000010100000101001011011110
Run Code Online (Sandbox Code Playgroud)

似乎为 Data 类型的变量 a 和 b 添加了填充,而没有为类型 c 和 d 添加了填充。为什么会这样呢?

pma*_*ane 5

迂腐的答案可能是 C++ 语言规范不保证局部变量的地址可能是什么。它们可能彼此相邻,或者可能有填充,或者它们可能完全不相关!语言律师可能会乐意就此打住。

如果您问为什么特定编译器会这样做,您可以修改您的问题(或添加标签)来指定这一点。

请注意,在您实际获取这些自动变量的地址之前,这些自动变量可能甚至没有地址 - 它们只是存在于寄存器中。对于变量来说可能更是如此char

所以这就是我的猜测 - 您使用的编译器很乐意将自动char变量打包到堆栈上(当您获取它们的地址时),但不愿意以struct同样的方式打包自动变量。