C++ 堆栈中的内存分配

C++ 堆栈中的内存分配,c++,C++,我有以下代码: #include <iostream> using namespace std; int main() { int i, j; int *p = &i; cout << "Address of i = " << &i << endl; cout << "Address of j = " <

我有以下代码:

#include <iostream>
using namespace std;
int main()
{   
    int i, j;
    int *p = &i;    
            
    cout << "Address of i = " << &i << endl;
    cout << "Address of j = " << &j << ", which is " << &i - 1 << endl;
    cout << "Address of p = " << &p << ", which is NOT " << &j - 1 << endl;
}
我认为局部变量,如int或pointer,是在堆栈中连续分配的。所以我期待着

Address of i = 0x61fe1c
Address of j = 0x61fe18
Address of p = 0x61fe14
我错过了什么

编辑:我想我明白了。指针指向变量的低位地址

#include <iostream>
using namespace std;
int main()
{   
    int i, j;
    int *p;
    int k, x;
            
    cout << "Address of i = " << &i << endl;
    cout << "Address of j = " << &j << ", which is " << &p + 1 << endl;
    cout << "Address of p = " << &p << ", which is " << &k + 1 << endl;
    cout << "Address of k = " << &k << ", which is " << &x + 1 << endl;     
}   
正如预期的那样。

你并没有真正遗漏任何东西,但你的预期几乎没有依据

大多数编译器通常使用所谓的“自然对齐”,这意味着项的大小也是它所需的对齐方式。例如,如果您分配一个4字节的项,它将被分配到一个4的倍数的地址。同样,一个8字节的项,它将位于一个8的倍数的地址

在某些情况下,对齐更为严格,因此(例如)一个16字节的项可能需要对齐到一个32的倍数的地址。这对于“矢量化”类型尤其常见,这些类型在一个大数据块中包含多个操作数,并同时对多个操作数进行操作(例如,Intel AVX或PowerPC Altivec)

举个例子,如果我有这样的东西:

int main(){
字符x;
int-y;
}
我通常的期望是在
x
y
之间看到3或7个未使用的字节(如果sizeof(int)==4,则填充3个字节;如果sizeof(int)==8,则填充7个字节)。这并不是严格要求的,但非常普遍,如果不这样做,会有点令人惊讶


但不管确切的推理是什么,编译器都可以在局部变量之间插入它认为合适的填充。在某些情况下(特别是对于调试),它们可以/将插入额外的空间并用已知值填充。然后在退出例程的过程中,他们将检查这些值是否保持完整,以合理地保证代码没有写入内存,而不应该写入内存。

是否有原因存储变量的实际内存地址对您很重要?这里有一个提示:在您的计算机上,
sizeof(int)==4
,以及
sizeof(int*)==8
我认为像int或pointer这样的局部变量是在堆栈中连续分配的——这是从哪里得到的(false)信息?我认为执行
&I-1
&j-1
是未定义的行为。对于当前的讨论和这个小程序来说可能不重要。但不是应该进入生产代码的内容。堆栈本身是连续的。但是编译器没有义务将您声明的变量放入部分将顺序添加到堆栈上。
#include <iostream>
using namespace std;
int main()
{   
    int i, j;
    int *p;
    int k, x;
            
    cout << "Address of i = " << &i << endl;
    cout << "Address of j = " << &j << ", which is " << &p + 1 << endl;
    cout << "Address of p = " << &p << ", which is " << &k + 1 << endl;
    cout << "Address of k = " << &k << ", which is " << &x + 1 << endl;     
}   
Address of i = 0x61fe1c
Address of j = 0x61fe18, which is 0x61fe18
Address of p = 0x61fe10, which is 0x61fe10
Address of k = 0x61fe0c, which is 0x61fe0c