为什么sizeof操作员返回的结构尺寸大于结构成员的总尺寸?
系统要求某些基元与存储器内的某些点对齐(对于4的倍数的字节,对于2的倍数的字节的短路,等等).当然,这些可以被优化以浪费填充中的最小空间.
我的问题是GCC为什么不自动执行此操作?更明显的启发式(从最大尺寸要求到最小尺寸的订单变量)是否缺乏某种方式?一些代码是否依赖于其结构的物理排序(这是一个好主意)?
我只是问,因为GCC在很多方面都是超级优化的,但不是在这个方面,我认为必须有一些相对很酷的解释(我不知道).
假设我有这样的结构:
struct MyStruct
{
uint8_t var0;
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
这可能会浪费很多(不是很多)空间.这是因为uint32_t变量的必要对齐.
实际上(在对齐结构以便它实际上可以使用uint32_t变量之后)它可能看起来像这样:
struct MyStruct
{
uint8_t var0;
uint8_t unused[3]; //3 bytes of wasted space
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
更有效的结构将是:
struct MyStruct
{
uint8_t var0;
uint8_t var2;
uint8_t var3;
uint8_t var4;
uint32_t var1;
};
Run Code Online (Sandbox Code Playgroud)
现在,问题是:
为什么编译器禁止(按标准)重新排序结构?
如果对结构进行重新排序,我认为你没有任何方法可以用脚射击自己.
例如,我有一个class,
class naive {
public:
char a;
long long b;
char c;
int d;
};
根据我的测试程序,a对d被陆续建成,像
a------- bbbbbbbb c---dddd
- 意味着未使用
为什么C++不能让它变得更紧,比如
ac--dddd bbbbbbbb
我似乎无法在文档中找到它,是否可以保证字段中的顺序与结构中声明的顺序相匹配?我知道它似乎在逻辑上(由于内存布局),它似乎也以这种方式执行,但只是确保.如果这不是保证,我不希望代码稍后破坏.
例如,如果我有
type Foo struct {
bar string `tag:"bar"`
baz string `tag:"baz"`
barbaz string `tag:"barbaz"`
}
Run Code Online (Sandbox Code Playgroud)
我运行了这段代码:
var c Foo
t := reflect.TypeOf(c)
nf := t.NumField()
tags := make([]string, nf)
for f := 0; f < nf; f++ {
tags[f] = t.Field(f).Tag.Get("tag")
}
Run Code Online (Sandbox Code Playgroud)
会tags保证是["bar", "baz", "barbaz"]吗?
我知道编译器可能会在结构中添加一些填充字节.但是,当编译器发现我们从未从结构中的变量中读取时,结构的大小会比成员的总大小小吗?
struct Foo_T
{
int a;
intmax_t b;
};
void bar(void)
{
struct Foo_T foo;
foo.a=rand();
someFunction(foo.a);
//i never access foo.b, only foo.a
if(sizeof(foo)< sizeof(int)+sizeof(intmax_t))
{
//is it possible that we can end here?
}
}
Run Code Online (Sandbox Code Playgroud) 结构是C编程语言中的复合数据结构; 它们由诸如int和指针之类的基元组成,它们以相邻的方式放置在存储器中,例如阵列.
我的问题是,结构本身是由什么构成的?它们是一种阵列吗?例如,哈希表可以实现为链表列表.以类似的方式,什么是实现的结构?如果需要,请在x86汇编级别解释.谢谢.
问题:有没有一种自动进行结构打包的方法?
背景:
结构打包对于减少某些基础数据的内存成本非常有用。基本上,这是通过对内部数据重新排序来实现最小内存成本的技巧。我的问题是有没有一种自动方法可以做到这一点?例如,我这里有一个struct Foo。(假设32位)
struct Foo {
char flag;
char* p;
short number;
};
Run Code Online (Sandbox Code Playgroud)
经过自动检查(无论是否是脚本,无论是否是本机),我应该获得 Foo 的内存优化版本,即:
struct Foo {
char* p;
short number;
char flag;
};
Run Code Online (Sandbox Code Playgroud)
这只是一个玩具示例。考虑下面更困难的情况,手动重新排序将是一项相当艰巨的工作。
结构具有依赖结构:
struct Foo {
char* p;
short number;
MoreFoo more_foo // How to deal with this?
char flag;
};
Run Code Online (Sandbox Code Playgroud)struct 位于遗留代码中,并且您不熟悉代码库。
我不考虑使用“packed”属性,因为它会导致一些性能问题。
有没有一种方法可以在类似C的结构中执行自动字段重新排序?我的意思是使用语言功能(例如C和C ++的预处理器以及C ++的模板/类型特征/ etc),这使得可以执行以下宏(类似于Boost.Fusion的样式来适应结构):
REARRANGE(StructureName,
(int8_t)(FieldName1),
(int32_t)(FieldName2),
(int16_t)(FieldName3),
(int32_t)(FieldName4));
// is equivalent to (without loss of generality):
struct StructureName
{
int32_t FieldName2;
int32_t FieldName4;
int16_t FieldName3;
int8_t FieldName1;
};
Run Code Online (Sandbox Code Playgroud)
当然,方法应考虑字段的alignof值(以及sizeof),并在可能的情况下考虑#pragma pack当前值。
我知道结果的可移植性很差,但这仅用于本地使用。
必须将字段名称以及相应的类型保存在一起。
目的是减小总结构尺寸。