我正在寻找一种在编译器对齐之前获取结构/类的原始大小的方法(更明显地让结构/类的成员字段的总和),如下所示:
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以获得更好的性能(
答案 0 :(得分:0)
没有。 C ++不提供该功能。将来,当众多反思提案中的一个将进入标准时,您可能能够获得所有成员的大小。然而,它几乎毫无意义,不可能做你想要的。原因如下:
1)在您的示例中,struct {char; int; };
始终为8个字节长,无论成员的顺序如何。总共将有3个字节的填充:在char
和int
之间,最后是int
和char
之间的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
}