【问题标题】:Data structure padding数据结构填充
【发布时间】:2011-05-17 01:19:45
【问题描述】:

什么是 c++ 中的数据结构填充以及如何检查填充字节的字节数?

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

【问题讨论】:

  • 我读过 sizeof 运算符返回大小以及填充字节,所以我只是想知道。
  • 好的,很公平。如果您只是出于好奇而感兴趣,那么以下两个答案是合理的。您不应该试图找出有关填充的信息,这样您就可以编写对其进行假设的代码。这样的代码可能不可移植。

标签: c++ data-structures


【解决方案1】:

处理器要求某些类型的数据具有特定的对齐方式。例如,处理器可能要求int 位于 4 字节边界上。因此,例如,int 可以从内存位置 0x4000 开始,但不能从 0x4001 开始。所以如果你定义了一个类:

class a
{
public:
    char c;
    int i;
};

编译器必须在ci 之间插入填充,以便i 可以从4 字节边界开始。

【讨论】:

  • 意味着如果您的示例从字节边界开始,您将不会有任何填充。它应该是。
  • 对于您可能遇到的绝大多数处理器/编译器,这个答案通常是正确的。只是不要依赖它总是准确无误。
  • "处理器需要" - 有时是正确的,有时不需要(即,如果未对齐,它不会 SIGBUS 或类似的),但性能更好。
  • 不完全正确。大多数处理器都是字节可寻址的,因此整数可以从任何字节地址开始。但是,编译器会将 int 放置在 4/8 字节边界上,因为 CPU 处理内存操作的方式会提高系统性能。
【解决方案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;
}

【讨论】:

    【解决方案3】:

    填充是出于性能原因 - 请参阅这篇文章 Data Structure Alignment 了解更多信息。

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

    #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 个字节。每个 int 是 4 个字节(可以用 sizeof(int) 确认)。没有填充。

    与班上的不同成员一起尝试,例如:

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

    【讨论】:

    • “出于性能原因进行填充”...有时,有时如果要求访问未对齐的数据,CPU 将实际上是 SIGBUS 或类似的。
    【解决方案4】:

    Lol 只需创建 2 个相同的结构,将其中一个打包 例如

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

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

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 2018-02-14
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多