数据结构填充

4
什么是C++中的数据结构填充,如何检查填充字节数?
class a { public: int x; int y; int z; };

我已经阅读了sizeof运算符返回大小以及填充字节,所以我只是想知道。 - parc65
好的,说得对。如果你只是出于好奇想了解,下面的两个答案是合理的。你不应该试图了解填充(padding)的信息,以便编写假定填充的代码。这样的代码可能不具备可移植性。 - andrewdski
4个回答

4
处理器要求某些类型的数据具有特定的对齐方式。例如,处理器可能需要一个 int 在 4 字节边界上。因此,例如一个 int 可以从内存位置 0x4000 开始,但不能从 0x4001 开始。所以如果您定义了一个类:
class a
{
public:
    char c;
    int i;
};

编译器需要在c和i之间插入填充以便i能够从4字节边界开始。

如果在字节边界上启动示例,则您的示例中不应该有填充。 - zsalzbank
这个答案通常适用于你可能遇到的绝大多数处理器/编译器。只是不要指望它总是精确无误地正确。 - andrewdski
处理器需要 - 有时是真的,有时则不是必需的(即使未对齐也不会出现SIGBUS或类似问题),但性能会更好。 - Tony Delroy
不完全正确。大多数处理器都是字节寻址的,因此整数可以从任何字节地址开始。然而,编译器会将 int 放置在 4/8 字节边界上,因为这样做可以增加系统性能,原因是 CPU 处理内存操作的方式。 - wk1989

2
struct A
{
    char c;
    int i;
};

int main(int argc, char *argv[])
{
    A a;

    cout << "sizeof struct = " << sizeof(A) << endl;

    cout << "sizeof items  = " << sizeof(a.c) + sizeof(a.i) << endl;

    return 0;
}

0

填充是出于性能考虑而进行的 - 请参阅此文章数据结构对齐以获取更多信息。

要查看编译器是否对您的数据结构进行了填充,您可以编写一个简单的程序:

#include <iostream>

class a {
public:
    int x;
    int y;
    int z;
};

int main()
{
    std::cout << sizeof(a) << std::endl; // print the total size in bytes required per class instance

    a anInstance;
    std::cout << &anInstance.x << std::endl; // print the address of the x member
    std::cout << &anInstance.y << std::endl; // as above but for y
    std::cout << &anInstance.z << std::endl; // etc
}

我添加了公共声明以避免编译器错误 - 这不会影响大小或填充。

编辑:在我的 MacBook Air 上运行此代码将输出以下内容: 12 0x7fff5fbff650 0x7fff5fbff654 0x7fff5fbff658

这表明在我的机器上,总大小为12字节,每个成员相隔4字节。整数每个占用4字节(可以使用sizeof(int)确认)。没有填充。

尝试在您的类中使用不同的成员进行测试,例如:

class b {
    public:
        char      w;
        char      x[6];
        int       y;
        long long z;
};

2
“填充是出于性能原因而进行的”...有时,如果要访问非对齐数据,CPU实际上会发出SIGBUS或类似的信号。 - Tony Delroy

0

哈哈,只需创建两个相同的结构体,将其中一个打包即可 例如:

struct foo {
  int  a;
  char b;
  int  c;
} 

struct bar {
  int  a;
  char b;
  int  c;
} __attribute__((__packed__));

sizeof(foo) - sizeof(bar)会给你填充的数量。或者像Duck建议的那样手动计算。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接