sol*_*var 12 c++ memory object char
我用C++创建了一个简单的类Storer,用于分配内存.它包含六个字段变量,所有这些变量都在构造函数中分配:
int x;
int y;
int z;
char c;
long l;
double d;
Run Code Online (Sandbox Code Playgroud)
我对如何存储这些变量感兴趣,所以我编写了以下代码:
Storer *s=new Storer(5,4,3,'a',5280,1.5465);
cout<<(long)s<<endl<<endl;
cout<<(long)&(s->x)<<endl;
cout<<(long)&(s->y)<<endl;
cout<<(long)&(s->z)<<endl;
cout<<(long)&(s->c)<<endl;
cout<<(long)&(s->l)<<endl;
cout<<(long)&(s->d)<<endl;
Run Code Online (Sandbox Code Playgroud)
我对输出很感兴趣:
33386512
33386512
33386516
33386520
33386524
33386528
33386536
Run Code Online (Sandbox Code Playgroud)
为什么char c占用四个字节?sizeof(char)当然返回1,那么为什么程序分配的内存超出了它的需要?这证实使用以下代码分配了太多内存:
cout<<sizeof(s->c)<<endl;
cout<<sizeof(Storer)<<endl;
cout<<sizeof(int)+sizeof(int)+sizeof(int)+sizeof(char)+sizeof(long)+sizeof(double)<<endl;
Run Code Online (Sandbox Code Playgroud)
打印:
1
32
29
Run Code Online (Sandbox Code Playgroud)
确实确实,不必要地分配了3个字节.任何人都可以向我解释为什么会这样吗?谢谢.
小智 24
数据对齐和编译器填充说嗨!
该CPU没有概念型的,它获取其32位(或64位或128位(SSE),或256位(AVX) - 让我们保持在32简单)寄存器需要正确对齐以便正确有效地处理.想象一个简单的场景,你有一个char,然后是一个int.在32位架构中,char为1字节,整数为4字节.
一个32位寄存器必须在其边界上断开,只占用整数的3个字节,并留下第四个字节用于"第二次运行".它无法以这种方式正确处理数据,因此编译器将添加填充以确保所有内容都得到有效处理.这意味着根据相关类型添加一定量的填充.
计算机不是人类,它不能用一双眼睛和大脑来挑选它们.它必须是非常确定的,并且对于如何做事情持谨慎态度.首先,它加载包含给定信息n个字节一个块,所以它删掉了那些无关的信息,然后又再次转向了一堆不必要的字节这没有什么,在做手工的操作和周围接班只有这样才能做必要的操作.通常你有两个操作数,这只是一个完整的操作数.当你完成所有这些工作时,才能真正处理它.如果你可以简单地对齐数据,那么就会产生太大的性能开销(而且大多数情况下,编译器会为你做这件事,如果你没有做任何花哨的话).
在视觉上 - 第一个绿色字节是提到的字符,三个绿色字节加上第二个块的第一个红色字节是4字节的int,在4字节访问边界上进行颜色编码(我们说的是32位寄存器).底部的"替代部分"显示了一个理想的设置,其中int正确地击中了寄存器(字符在图像的某处被填充到服从):
更多的数据比对,当你处理设置像SSE(128位的REG)或AVX(256位的REG)指令的花哨扩展,并配备相当方便,所以特别必须注意,这样的优化矢量化不会失败(对齐SSE的16字节边界,16*8 - > 128位).
phonetagger在注释中提出了一个有效点,即pragma指令可以通过预处理器分配给强制编译器,以便以用户程序员指定的方式对齐数据.但是,这样的指令#pragma pack(...)
是对编译器的一种陈述,即你知道你正在做什么以及什么对你最好.确保你这样做,因为如果你无法适应你的环境,你可能会遇到各种各样的惩罚 - 最明显的是使用你自己没有编写的外部库,这些库在打包数据的方式上有所不同.
当他们发生冲突时,事情就会爆炸.在这种情况下,最好是建议谨慎,并且真正与手头的问题保持密切联系.如果您不确定,请将其保留为默认值.如果你不确定但是必须使用像SSE那样的对齐为王(并且不是默认也不是简单的远程),请在线查询各种资源或在此处提出另一个问题.
我会做一个类比来帮助你理解.
假设有一条长条面包,你有一台切割机可以切成相同厚度的切片.然后你给这些面包,让我们说儿童.每个孩子都会拿起他们的面包并公平地做他们想做的事情(把Nutella放在他们身上然后吃饭等).他们甚至可以从中制作更薄的切片并像这样使用它.
如果一个孩子走近你并且说他不想要那片每个人都会得到,但是更薄的切片,那么你会遇到困难,因为你的切割机经过优化可以减少至少一个最小量,这让每个人都开心.但是当一个孩子要求更薄的切片时,你必须重新发明机器或者增加其它复杂性,就像引入两种切割模式一样.你不希望这样.最终你放弃了,无论如何只是给他一个大片.
这就是它发生的原因.希望你能与这个类比联系起来.