是否有一种巧妙的方法可以避免在 C++ 中使用嵌套类进行额外填充?

Dev*_*vyy 12 c++ padding inner-classes memory-alignment compiler-optimization

这些结构体align1andalign2包含相同的数据,但align1由于嵌套布局而具有更多填充。我怎样才能获得align2while的内存节省对齐,同时也使用像 in 这样的嵌套结构align1

int main() {
    struct align1 {
        struct {
            double d;    // 8 bytes
            bool b1;    //+1 byte (+ 7 bytes padding) = 16 bytes
        } subStruct;
        bool b2;        //+1 byte (+ 7 bytes padding) = 24 bytes
    };
    struct align2 {
        double d;        // 8 bytes
        bool b1, b2;    //+2 byte (+ 6 bytes padding) = 16 bytes
    };

    std::cout << "align1: " << sizeof(align1) << " bytes\n";    // 24 bytes
    std::cout << "align2: " << sizeof(align2) << " bytes\n";    // 16 bytes

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

subStruct需要嵌套结构,因为它将在外部声明/定义。我正在使用C++17Visual Studio 2017

生成的代码可能脏兮兮的,也可能看起来很糟糕。我只是不希望它稍后向我抛出随机错误或在更改配置时中断。

Yun*_*sch 4

我明确依赖于提出“肮脏或难看”的代码的许可......任何东西。更清楚地说,我只是提供一个想法。你需要考验自己,自己承担责任。我认为这个问题明确允许未经测试的代码。

有了这个代码:

typedef union
{
    struct
    {
        double d;   // 8 bytes
        bool b1;    //+1 byte (+ 7 bytes padding) = 16 bytes
    } nested;
    struct
    {
        double d;       // 8 bytes
        bool b1, b2;    //+2 byte (+ 6 bytes padding) = 16 bytes
    } packed;
} t_both;
Run Code Online (Sandbox Code Playgroud)

我期望以下属性/功能:

  • 包含在其他地方可能类型定义的子结构(可以从包含的头文件中使用)
  • 子结构可通过XXX.nested.dand访问XXX.nested.b1
  • 与以下地址相同XXX.packed
  • 访问XXX.packed.b2被认为是填充的内容nested
  • 两个子结构具有相同的总大小,我希望这意味着即使制作这个数组也可以

无论您对此做什么,它都可能与以下要求相冲突:在写入和读取联合时,所有读取访问都必须与最近的写入访问联合的同一部分。因此,写一个而读另一个是不被严格允许的。这就是我认为该代码提案不清楚的地方。也就是说,我经常在各自的构造已经明确测试过的环境中使用这种联合。

为了说明这里是一个功能相同但同样不干净的版本,它更好地说明了子结构可以在其他地方定义:


/* Inside an included header "whatever.h" : */
typedef struct
{
    double d;   // 8 bytes
    bool b1;    //+1 byte (+ 7 bytes padding) = 16 bytes
} t_ExternDefedStruct;
Run Code Online (Sandbox Code Playgroud)
/* Content of including file */

#include "whatever.h"

typedef union
{
    t_ExternDefedStruct nested;
    struct
    {
        double d;       // 8 bytes
        bool b1, b2;    //+2 byte (+ 6 bytes padding) = 16 bytes
    } packed;
} t_both;
Run Code Online (Sandbox Code Playgroud)