为什么后面跟着字符串时字符填充较少

Why is character padding is less when followed by string

提问人:archana 提问时间:5/22/2023 更新时间:7/14/2023 访问量:61

问:

根据我在 64 位操作系统中的知识,在读取类变量时,为了减少 CPU 周期,c++ 编译器会进行填充并尝试将数据放入 8 个字节的块中。现在在下面的程序中,由于 int i 和 j 将占用一个 8 字节,并且可以在没有额外 CPU 周期的情况下读取,因此如果字符 'name' 不填充 7 个字节,以便字符串将在 3 个 8 字节的周期内顺利读取。如果是这样,sizeof(e1) 应该返回 40.但它只返回 36.为什么会这样?注意:如果我在字符后面加倍,这需要 8 个字节,那么该字符将被填充 7 个字节,则 e1 的大小返回为 24。我的操作系统是 64 位。

#include <iostream>

     using namespace std;

     class emp{

        public:
          int i;            //needs 4 bytes
          int j;            //needs 4 bytes
          char name;        //should be padded by 7 bytes
          string s;         //needs 24 bytes
         //double d;        //needs 8 bytes.
    };

    int main()
    {
     emp e1;
     cout<<sizeof(e1);
    }

答案应该是40分,但我得到的是36分。

C++ 变量 padding 成员

评论

2赞 Jeremy Friesner 5/22/2023
打印出每个成员变量的 alignof() 运算符返回的值是检查您对每个项目的对齐要求的想法是否与编译器的想法一致的好方法。
0赞 Andreas Wenzel 5/22/2023
在您的问题中,您声明您使用的是 64 位操作系统。但是,在编译时,是否还要创建 64 位可执行文件?或者您是否正在创建一个 32 位可执行文件?您使用的是哪种编译器,您究竟是如何编译程序的?
0赞 archana 5/22/2023
@AndreasWenzel是的,我检查了它正在创建 64 位 exec。
0赞 Red.Wave 5/22/2023
我不记得在任何地方读到内存布局中成员的顺序应该与声明相同。有一次,我最终在尝试访问结构的未对齐实例的成员时,使用从对齐对象计算的偏移量,向自己的脚开枪。不过,这是一个过时的工具链。编译器可以根据对齐方式更改子对象的位置。另一种更理智的可能性是 CPU 以正好一半的对齐方式读取单词,以牺牲更多的读取周期为代价。速度与内存的优化可以改变这种行为。
0赞 Andreas Wenzel 5/22/2023
请将该行添加到您的程序中,以便我们可以看到成员变量的确切地址。请注意,在 C++ 中,我认为使用更好的编码风格而不是 C 风格的强制转换。我只使用 C 型演员表,因为它们更短。cout<<'\n'<<(void*)&e1.i<<'\n'<<(void*)&e1.j<<'\n'<<(void*)&e1.name<<'\n'<<(void*)&e1.s<<'\n';reinterpret_cast

答:

0赞 Raman 7/14/2023 #1

通过我的调试,我发现你的“字符名”占用了 4 位的内存。 38

上述行为背后的原因是数据结构对齐和填充。基本上,如果您要创建一个 4 字节变量,例如 int,它将与一个 4 字节边界对齐,即它将从内存中的地址开始,该地址是 4 的倍数。这同样适用于其他数据类型。2 字节短应从偶数内存地址开始,依此类推。

因此,如果您在 int 之前声明了一个 1 字节字符(此处假设为 4 个字节),则中间将剩下 3 个可用字节。用于它们的常用术语是“填充”。

这是我从某个地方发现的,我认为这将帮助您理解..