可能重复:
为什么GCC不优化结构?
为什么C++不能使结构更紧凑?
请考虑以下32位x86计算机上的示例:
由于对齐约束,以下结构
struct s1 {
char a;
int b;
char c;
char d;
char e;
}
Run Code Online (Sandbox Code Playgroud)
如果成员被重新排序,则可以更有效地表示内存(12对8字节)
struct s2 {
int b;
char a;
char c;
char d;
char e;
}
Run Code Online (Sandbox Code Playgroud)
我知道C/C++编译器不允许这样做.我的问题是为什么语言是这样设计的.毕竟,我们最终可能会浪费大量的内存,而且struct_ref->b不会关心差异.
编辑:谢谢大家的非常有用的答案.您解释为什么由于语言的设计方式,重新排列不起作用.然而,它让我想到:如果重新排列是语言的一部分,这些论点是否仍然有效?让我们说有一些指定的重新排列规则,我们至少需要这个规则
我一个接一个地论证你的论点:
低级别的数据映射,"最惊喜的元素":只写你的结构以紧身款式自己(像@佩里的回答),并没有发生任何改变(要求1).如果由于一些奇怪的原因,你想要内部填充,你可以使用虚拟变量手动插入,和/或可能有关键字/指令.
编译器差异:要求3消除了这种担忧.实际上,从@David Heffernan的评论来看,我们今天似乎遇到了这个问题,因为不同的编译器填充不同?
优化:重新排序的重点是(内存)优化.我在这看到很多潜力.我们可能无法一起删除填充,但我没有看到重新排序如何以任何方式限制优化.
类型铸造:在我看来,这是最大的问题.不过,应该有办法解决这个问题.由于规则是用语言修复的,编译器能够弄清楚成员的重新排序方式,并做出相应的反应.如上所述,在您想要完全控制的情况下,始终可以防止重新排序.此外,要求2确保类型安全代码永远不会中断.
我认为这样的规则有意义的原因是因为我发现按结构内容而不是按类型对结构成员进行分组更为自然.当我有很多内部结构时,编译器也更容易选择最适合我的顺序.最佳布局甚至可能是我无法以类型安全的方式表达的布局.另一方面,它似乎使语言更复杂,这当然是一个缺点.
请注意,我不是在谈论改变语言 - 只有它可以(/应该)设计不同.
我知道我的问题是假设的,但我认为讨论提供了对机器和语言设计较低层次的更深入的了解.
我在这里很新,所以我不知道是否应该为此产生一个新问题.请告诉我是否是这种情况.
我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组,因此由于对齐而浪费了一些空间。
如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可能为12。
实现有可能执行此操作,还是该标准中的某些规则禁止这样做?
[不是结构填充和包装的重复。这个问题是关于填充的方式和时间。这是关于如何处理它的信息。]
我刚刚意识到C ++中的对齐会浪费多少内存。考虑以下简单示例:
struct X
{
int a;
double b;
int c;
};
int main()
{
cout << "sizeof(int) = " << sizeof(int) << '\n';
cout << "sizeof(double) = " << sizeof(double) << '\n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << '\n';
cout << "but sizeof(X) = " << sizeof(X) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
使用g ++时,程序将提供以下输出:
sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but …Run Code Online (Sandbox Code Playgroud) c++ optimization memory-alignment memory-layout struct-member-alignment
如果我有一个structC++,有没有办法安全地读/写一个跨平台/编译器兼容的文件?
因为如果我理解正确,每个编译器"填充"基于目标平台不同.
这是Rob Walker 在这里回答的问题.
假设我声明一个类/结构,如下所示:
struct
{
char A;
int B;
char C;
int D;
};
Run Code Online (Sandbox Code Playgroud)
是否可以安全地假设这些成员将在内存中以完全相同的顺序声明,或者这是否依赖于编译器?我问,因为我一直认为编译器可以随心所欲地做任何事情.
这导致了我的下一个问题.如果上面的例子导致内存对齐问题,为什么编译器不能只是隐式地将它变成这样的东西:
struct
{
char A;
char C;
int B;
int D;
};
Run Code Online (Sandbox Code Playgroud)
(我主要是询问C++,但我也有兴趣听到C答案)
我知道为什么GCC默认不重新排序结构的成员,但我很少编写依赖于结构顺序的代码,所以有什么方法可以标记我的结构自动重新排序?
C++编译器(特别是g ++)可以重新排序结构的内部元素吗?
我看到一些奇怪的行为,我有一个包含如下内容的结构:
Struct SomeStruct{
...
...
long someLong;
long someLongArray[25];
unsigned long someUnsignedLong;
unsigned long someUnsignedLongArray[8];
unsigned long int someUnsignedLongInt;
...
...
};
Run Code Online (Sandbox Code Playgroud)
当我写输出这个到文件,顺序someUnsignedLongArray和someLongArray似乎被反转(即,在元件someLongArray []出现之后someUnsignedLong和的元素someUnsignedLongArray []后出现someLong).这可能吗??
谢谢
更新:根据要求,我使用以下内容写出结构:
int fd = open(fspec,O_RDWR|O_CREAT|O_TRUNC,0666);
int writeRes = write(fd,(char *)&someStruct,sizeof(SomeStruct));
Run Code Online (Sandbox Code Playgroud)
为了完整性,这里是完整的结构:
struct SomeStruct{
byte someByte;
byte someByteArray[6];
char someChar;
char someCharArray[5];
char someCharArrayArray[3][5];
short someShort;
signed short someShortArray[2];
unsigned short someUnsignedShort;
unsigned short someUnsignedShortArray[8];
int someInt;
int someIntArray[3];
int someIntArrayArrayArrayArray[4][3][2][6]; …Run Code Online (Sandbox Code Playgroud) C++结构的布局是由标准设置的,还是至少在编译器之间是通用的?
我有一个结构,其中一个成员需要在16字节边界上对齐,如果我能保证字段的顺序,这将更容易.
另外,对于非虚拟类,第一个元素的地址是否也可能是结构的地址?
我对GCC和MSVS最感兴趣.
问题:有没有一种自动进行结构打包的方法?
背景:
结构打包对于减少某些基础数据的内存成本非常有用。基本上,这是通过对内部数据重新排序来实现最小内存成本的技巧。我的问题是有没有一种自动方法可以做到这一点?例如,我这里有一个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”属性,因为它会导致一些性能问题。
我正在线上学习操作系统课程,我完成了第一个课程http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall- 2012/assignments/MIT6_828F12_assignment1.pdf
但让我感到惊讶的是他们如何返回数据结构,他们使用数据结构并返回一个较小的数据结构,并使用它们只是将其转换回来.我看到它可以优化代码,但这样安全吗?这是好习惯吗?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct small
{
int n ;
};
struct big
{
int n ;
char * string ;
};
struct small* f()
{
struct big* x = malloc(sizeof(struct big));
x->n = 'X';
x->string = strdup("Nasty!");
return (struct small*) x ;
}
int main(int argc, char *argv[])
{
struct big *y = (struct big*)f();
printf("%s\n",y->string);
}
Run Code Online (Sandbox Code Playgroud)
编辑1:这是来自mit的链接,我只是在我自己的代码中复制了这个想法. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/assignments/sh.c