关于 C++ 中的长度、偏移和填充的问题 [重复]

Questions about length, offset, and padding in C++ [duplicate]

提问人:sion 提问时间:9/24/2023 最后编辑:πάντα ῥεῖsion 更新时间:9/24/2023 访问量:65

问:

我是一个刚开始学习 C++ 的初学者。在研究数据结构时,我有一个关于sizeof的问题,我想问一下。

#include <iostream>
using namespace std;

typedef char String[9];

// Definition of Student Record
struct StudentRecord
{
    String firstName;
    String lastName;
    int id;
    float gpa;
    int currentHours;
    int totalHours;
};

int main(int argc, const char * argv[]) {
    StudentRecord student;
    StudentRecord students[100];

    // Size of memory allocation for student
    cout << "sizeof(student): " << sizeof(student) << endl;
    // Size of memory allocation for students
    cout << "sizeof(students): " << sizeof(students) << endl;
    
    return 0;
}

在以下代码中:

cout << "sizeof(student): " << sizeof(student) << endl;

当我打印 sizeof(student) 时,它返回 36。但是,学生成员变量的大小从名字到结尾明确定义为 9、9、4、4、4、4。把它们加起来,我得到 34。但是,学生实例(即 StudentRecord 的实例)的大小为 36。

我很好奇这种 2 字节的差异是如何发生的。我从谷歌搜索中发现它与填充有关。所以,我知道 firstName 和 lastName 的大小都是 9,id 和 gpa 的大小各为 4,加起来是 8,这就是为什么添加了额外的填充大小 1 以匹配 firstName 和 lastName 的大小 9。同样,currentHours 和 totalHours 的附加填充大小也为 1,因此总大小为 36。

我的理解正确吗?谢谢!

我想了解在实际计算机上发生的填充过程。

C++ 填充 sizeof

评论


答:

0赞 Ahmed AEK 9/24/2023 #1

您必须满足所有基本类型的对齐要求,double 或 long 应与 8 字节对齐,int/float 应与 4 字节对齐,char 应与 1 字节对齐。

struct StudentRecord
{
    char names[18];
    // char padding[2]; // done by compiler.
    int id;
    float gpa;
    int currentHours;
    int totalHours;
};

在您的对象中,您的 2 个字符串的总长度为 9 + 9 = 18,后跟一个 ,这必须对齐为 4 个字节,因此编译器在 18 个字符之后插入 2 个字节的填充,因此 18 + 2 = 20,20 % 4 = 0,现在正确对齐为 4 个字节。intintid

评论

0赞 sion 9/24/2023
我看到我完全困惑了。我现在完全理解了。谢谢!!
0赞 Homer512 9/24/2023 #2

旁注:你会把其他程序员和你的.typedef char[9] String

无论如何:

  • 每种类型的对齐方式通常与其标量大小相同
  • 前两个成员是 (alignment 1 字节) 的数组。第二个成员在对象内的字节偏移量 18 处结束char
  • 第三个成员是 .在大多数平台上,这是 4 个字节,4 个字节对齐。18 不是 4 的倍数。因此,我们添加了 2 个字节的填充。将从对象开头的字节偏移量 20 开始intid
  • 所有剩余成员也是 4 字节,具有 4 字节对齐方式,因此不需要进一步的填充
  • 内部大小为 9+9+2(填充)+4+4+4+4 = 36 字节
  • 对象的总大小需要是其对齐方式的倍数。类或结构的对齐方式派生自其任何成员的最大对齐方式。这是 和 的 4 个字节。36 已经是 4 的倍数,因此我们不需要在对象的背面进一步填充intfloat

评论

0赞 sion 9/24/2023
我看到我完全困惑了。我现在完全理解了。谢谢!!