为什么连续的整型变量在内存中的间隔不是4个字节?

问题描述 投票:0回答:1

我有以下 C++ 代码:

#include <iostream>
#include <string>

using namespace std;

int main()
{
   int varInt = 123456;
   string varString = "DefaultString";

   cout << "varInt (0x" << &varInt << ") = " << varInt << endl;
   cout << "varString (0x" << &varString << ") = " << varString << endl;
}

这是我的输出:

我的问题是:既然整数是 4 个字节,那么变量 varString 不应该在内存中与 varInt 相距 4 个字节吗? IE。 varString 应位于 0x00000027 2B F7 F4 44

c++ windows memory operating-system compiler-construction
1个回答
0
投票

C++ 作为一种语言并不能保证堆栈变量(局部变量)的位置。因此,您的结果将根据操作系统、架构、编译器、优化设置的不同而有所不同...... 只要您不尝试获取它的地址,甚至不能保证整数变量位于任何地址,并且如果函数允许并且使用优化,则可以将其提升到寄存器中。

至于为什么字符串变量实际上会超过 4 个字节:对齐。编译器将尝试将变量放置在一个地址处,该地址是它们自然对齐的倍数。详细信息还取决于您的环境,但根据经验,x64 的对齐方式是 8 字节,任何大于或等于 8 字节的结构都将放置在此类对齐的地址处。您显示的“varString”地址的模数与 8 字节对齐,因为 (address % 8) == 0。如果将其放置在您建议的地址处,则不会给出该对齐。

我不是对齐技术细节方面的专家,但这样做主要是出于性能原因。我认为较旧的 CPU 甚至无法处理未对齐的地址,较新的 CPU 具有隐藏的惩罚,而在现代 CPU 上,我认为没有太大的惩罚,除非您在尝试访问值时跨越缓存行边界(当事物对齐时就不会发生这种情况)。 当我们讨论通过 XMM 处理的 16 字节类型时,情况有所不同,在这种情况下,对齐对于性能来说仍然非常必要(或者如果不保留,甚至可能在某些指令上出现段错误)。

所以底线是,编译器不会尝试保留尽可能多的空间,尤其是局部变量,而是尝试实现对齐。上次我检查时,MSVC 的调试版本甚至不会在释放局部变量后(即在 {} 中声明或不再使用时)尝试重用局部变量的空间,但如前所述,这是一切取决于实施。

© www.soinside.com 2019 - 2024. All rights reserved.