C++中栈和堆的地址
Posted
技术标签:
【中文标题】C++中栈和堆的地址【英文标题】:Address of Stack and Heap in C++ 【发布时间】:2011-04-01 08:37:13 【问题描述】:更正:
我把指针地址的概念和指针指向的地址搞混了,所以修改了下面的代码。现在它打印出我想要的内容,变量 a、c、i、j、k、p 在堆栈上,变量 b、d 在堆上。静态和全局变量在另一个段上。非常感谢大家!
好吧,我知道这两个概念已经深入讨论了……但我仍然对以下代码有疑问:
#include <iostream>
using namespace std;
class A
;
int N = 10;
void f(int p)
int j = 1;
float k = 2.0;
A c;
A* d = new A();
static int l = 23;
static int m = 24;
cout << "&c: " << &c << endl;
cout << "&d: " << d << endl;
cout << "&j: " << &j << endl;
cout << "&k: " << &k << endl;
cout << "&l: " << &l << endl;
cout << "&m: " << &m << endl;
cout << "&p: " << &p << endl;
int main()
int i = 0;
A* a;
A* b = new A();
cout << "&a: " << &a << endl;
cout << "&b: " << b << endl;
cout << "&i: " << &i << endl;
cout << "&N: " << &N << endl;
f(10);
return 0;
我的结果是:
&a: 0x28ff20
&b: 0x7c2990
&i: 0x28ff1c
&N: 0x443000
&c: 0x28fef3
&d: 0x7c0f00
&j: 0x28feec
&k: 0x28fee8
&l: 0x443004
&m: 0x443008
&p: 0x28ff00
这很有趣,因为除了全局变量 N 和函数 f 中的两个静态变量 l 和 m 之外,所有其他变量的地址似乎都在一起。 (注:代码和结果已被修改,与这里所说的不符。)
我搜索了很多关于堆栈和堆的信息。常识是,如果一个对象是由“new”创建的,那么它就在堆上。并且局部变量(例如上面示例中的 j 和 k)在堆栈上。但在我的示例中似乎并非如此。是依赖不同的编译器,还是我的理解有误?
非常感谢大家。
【问题讨论】:
从您的问题中我不明白为什么您认为根据您显示的地址,一个变量在堆栈或堆上。 这真是毫无意义。你无法推断你的记忆在哪里 Proper stack and heap usage in C++? 的可能重复项 我不喜欢提议的副本,但我投票给 NaRQ,因为该帖子是基于对 OP 的误解,现在已经澄清了,没有问题了。 @Zhongxia:如果您仍然对这里发生的事情感兴趣,您可能需要阅读“数据段”。 【参考方案1】:你的理解是错误的。例如b
是一个指针——如果你想要new
创建的对象的地址,你需要打印出b
,而不是&b
。 b
是一个局部变量,所以它本身(在&b
找到)在堆栈上。
对于您的示例,N
、l
和 m
可能位于可执行文件的数据部分中。如您所见,它们具有相似的地址。您要打印的每个其他变量都在堆栈上 - 它们的地址同样彼此相似。其中一些是指向从堆分配的对象的指针,但您的打印输出都不会显示。
【讨论】:
【参考方案2】:如果你想打印d
指向的任何地址(在这种情况下它指向堆上的一个对象),请执行
cout << "d: " << d << endl;
那会打印指针的值,而指针的值就是它所指向的对象的地址。
你的代码有
cout << "&d: " << &d << endl;
这将打印 d
的地址,正如您在 main 中定义的 d
一样,它将在堆栈上,您正在打印指针的地址。有指针本身和它指向的对象,它们是两个不同的东西,有不同的地址。
【讨论】:
【参考方案3】:你的理解是正确的。
局部变量在堆栈上分配。 动态分配的对象在堆上分配。尽管您在示例中始终使用局部变量的地址。
示例:打印出d
而不是d
的地址。因为d
是一个局部变量(所以地址类似于c
),但它是一个指针变量,指向一个动态分配的对象(that is on the heap)
。
编译器如何实现堆栈和堆会有所不同。
在现代操作系统中,堆栈和堆甚至可以共享同一个区域(即,您可以通过在堆中分配块来实现堆栈)。
【讨论】:
这是真的,但不是 OP 获得他的价值观的原因。 :-)【参考方案4】:从纯 C++ 的角度来看,这两种形式之间的区别仅与对象生命周期的管理方式有关。
From here, good read
【讨论】:
【参考方案5】:静态变量在数据段中。你也可以混合指针的地址和它的值。例如:
a 是堆栈上 A* 类型的局部变量。 &a 还给出了实际存在的地址(在堆栈上)。 a的值是A类型的堆对象的地址;
【讨论】:
【参考方案6】:你不能依赖不同的编译器以同样的方式做事。对于几乎每一段代码你都会写出栈和堆的区别是没有意义的。不用担心。
【讨论】:
【参考方案7】:在您的示例中,唯一不“在一起”的是l
、m
和N
。它们是两个静态变量和一个全局变量,因此它们肯定不会分配在堆栈上。它们也不是来自堆,很可能它们来自模块的 .data 段。堆中唯一的地址应该是b
指向的地址,但您打印的是b
本身的地址,而不是它指向的地址。
【讨论】:
还要注意你的“neirness”是特定于平台的。在像 IA64 这样带有“后备存储”堆栈的平台上,地址可能看起来完全不同(即&p
与&j
“远”),请参阅blogs.msdn.com/b/slavao/archive/2005/03/19/399117.aspx【参考方案8】:
人们可能无法安全地假设堆栈中事物相对于堆中事物的相对地址,也不能安全地假设任何并非全部来自同一数组或分配的指针的相对地址(通过 malloc , calloc 等) 块。我什至不确定指针是否需要排名。
【讨论】:
以上是关于C++中栈和堆的地址的主要内容,如果未能解决你的问题,请参考以下文章