整数是如何存储在堆栈中的



main.cpp

#include <iostream>
int main(){
int x = 1, j = 2;
int *p = &j;
//    std::cout << &x << std::endl;
std::cout << *(p-1) << std::endl;
}

我通过注释掉和取消注释的行std::cout << &x << std::endl;得到不同的输出。整数是否存储在堆栈中的连续位置?

值:

commented: 0 (probably garbage value)
uncommented: 1

您没有使用x,因此编译器没有将其存储在的任何位置

请记住,当您编写C++时,您并不是在编写程序。您正在描述您希望编译器为您编写的程序的行为。编译器可以编写任何程序,只要它的行为与您描述的行为匹配即可。如果您声明的变量的初始化没有可观察到的副作用,并且您从未在任何地方使用过它,那么您就没有描述任何行为。编译器不需要生成任何代码来处理这个问题,所以它通常会完全省略这样的变量。


请注意,在这种情况下,您给出的指令没有任何定义的行为,因此编译器可以编写它想要的任何程序。试图将指针偏移到它所指向的数组之外是未定义的(其中非数组变量被视为一个元素的数组(,因此p - 1没有定义。

你正在做的是未定义的行为,你不应该尝试在任何严肃的程序中使用这些细节,而是尝试这个:

#include <iostream>
int main(){
int a = 42;
int b = 1;
int c = 2;
int d = 2;
int e = 2;
int *p = &c;
int *q=p+1;

std::cout << "sizeof(int) = " << sizeof(int) << 'n';
std::cout << "&a = " << &a << 'n';
std::cout << "&b = " << &b << 'n';
std::cout << "&c = " << &c << 'n';
std::cout << "&d = " << &d << 'n';
std::cout << "&e = " << &e << 'n';
std::cout << "q  = " << q << 'n';
}

典型输出:

sizeof(int) = 4
&a = 0x7fff7c418d74
&b = 0x7fff7c418d78
&c = 0x7fff7c418d7c
&d = 0x7fff7c418d80
&e = 0x7fff7c418d84
q  = 0x7fff7c418d80

您可能会看到q = &d(如这里所示(或q = &b

然后注释掉匹配的输出行。对我来说,这是std::cout << "&d = " << &d << 'n';

典型输出:

sizeof(int) = 4
&a = 0x7fff62baf498
&b = 0x7fff62baf49c
&c = 0x7fff62baf4a0
&e = 0x7fff62baf4a4
q  = 0x7fff62baf4a4

实际地址在执行之间会有所不同,但通常在int(通常为4(的大小方面具有固定的关系。

在我的平台上,你会看到int是4个字节,指针输出为十六进制地址,所有地址相差4。这是最常见的情况。

也就是说,在本例中,很可能在您的平台上,您会看到局部变量占用指针地址提供的连续内存块。

您最可能看到的是,当您的代码中不使用x(我的代码中为d(时,编译器会对其进行优化,使其不存在。

指针算术(例如p-1(仅在数组中有效。然而,p+1总是合法的,因为变量总是像单例数组一样,并且有一个特殊的规则允许指向数组末尾之后的一个。

未定义的是取消引用p+1,即使它指向其他变量之一(很可能会这样(。它不是"安全派生的指针"。

p-1可能会给你带来你所期望的结果!但p-1的结果是未定义的。

这说明了堆栈是如何工作的。永远不要(永远!(将此作为任何严肃编码工作的一部分。

最新更新