在编译器对齐之前,是否可以获得类/结构的原始大小?

时间:2016-10-02 17:21:28

标签: c++ struct alignment sizeof

我正在寻找一种在编译器对齐之前获取结构/类的原始大小的方法(更明显地让结构/类的成员字段的总和),如下所示:

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

sizeof(Foo)返回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&#39; s decltype可能有用!),关于有用的实现的任何想法?

修改:  我试图通过比较sizeof(type)和orig_sizeof(type),并且要求用户重新调整feild以获得更好的性能(

2 个答案:

答案 0 :(得分:0)

没有。 C ++不提供该功能。将来,当众多反思提案中的一个将进入标准时,您可能能够获得所有成员的大小。然而,它几乎毫无意义,不可能做你想要的。原因如下:

1)在您的示例中,struct {char; int; };始终为8个字节长,无论成员的顺序如何。总共将有3个字节的填充:在charint之间,最后是intchar之间的1,最后是2 ......这是不可能使用标准C ++构建“有效填充”结构。

2)继承。编译器可以在子成员的父结构中重用填充。其子集是空基优化,它可以使整个对象大小小于其基数和成员的总和。或不。 EBO不是强制性的。尝试确定EBO是否刚刚被触发并且struct“有效地打包”或者它被触发并且在某个地方有2个填充字节填充,这很有趣。

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

答案 1 :(得分:0)

您可以在单独的标题中使用条件编译来定义结构:

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

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

#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
}