是否有可能在编译器对齐之前获得 class/struct 的原始大小?

Is it possible to get the original size of the class/struct before compiler align it?

我正在寻找一种方法来在编译器对齐它之前获取 struct/class 的原始大小(更清楚地说,让我们说 struct/class 的成员字段的总和),如下所示:

struct Foo{
   char c;
   // the compiler will appen 3 bytes here
   int i;
};

sizeof(Foo) returns 8 但原来的大小是 5 .

假设我们要编写一个名为 orig_sizeof()

的模板函数或宏
template <class t>
size_t orig_sizeof(t)
{
   // calculate the sum of the fields of t
}

当然sizeof是内部宏,没有源码的关键字宏

一种可能的方法是使用 __attribute__#pragma 更改结构对齐,而不是在将对齐恢复为默认值后使用 sizeof 获取大小(也许 c++11 的 decltype 可以很有用!),关于有用的实现有什么想法吗?

编辑: 我正在尝试编写一个优化的库,该库不接受未优化的 struct/class 作为参数,方法是将 sizeof(type) 与 orig_sizeof(type) 进行比较,并要求用户重新调整字段以获得更好的性能,如果可能

没有。 C++ 不提供该功能。将来,当众多反射提案中的一个进入标准时,您可能能够获得所有成员的规模。然而,它本质上是毫无意义的,并且不可能做你想做的事。原因如下:

1) 在您的示例中,无论成员的顺序如何,struct {char; int; }; 的长度始终为 8 个字节。总是会有 3 个字节的填充:在 charint 之间,在最后,在 intchar 之间有 1 个,在最后有 2 个......它是无法使用标准 C++ 构建 "effectivelly packed" 结构。

2) 继承。编译器可以为子成员重用父结构中的填充。其中的一个子集是空基优化,它可以使整个对象的大小小于其基和成员的总和。或不。 EBO 不是强制性的。尝试确定 EBO 是否只是没有被触发并且结构是 "effectivelly packed" 或者它被触发并且你在某处有 2 个杂散字节的填充很有趣。

3) 动态调度设施。通常它是 class 中的另一个不可见指针成员(或多个在多重继承的情况下),它将向 class 添加自己的对齐要求。然后 (1) 适用。更糟糕的是,您无法更改这些指针的放置位置。

您可以在单独的 header 中定义结构,并使用条件编译进行打包:

struct 
#ifdef pack
__attribute__((packed))
PackedFoo
#else
Foo
#endif
{
  char c;
  int i;
};

然后使用预处理器包含结构的打包和解包版本:

#include "foo.hpp"
#define pack
#include "foo.hpp"

这样您就可以观察到两种尺寸,就好像它们是同一类型一样:

//custom sizeof for packed representation
#define sizeof_packed(type) sizeof(Packed##type)

int main(){

  std::cout << sizeof(Foo) << '\n';        //prints 8
  std::cout << sizeof_packed(Foo) << '\n'; //prints 5
}