C ++中Stack和Heap的地址

时间:2010-08-19 20:38:41

标签: c++ stack heap

校正:

我搞砸了指针地址的概念和指针指向的地址,因此修改了以下代码。现在它打印出我想要的东西,变量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)在堆栈上。但在我的例子中似乎并非如此。它是否依赖于不同的编译器,或者我的理解是错误的?

非常感谢你们所有人。

8 个答案:

答案 0 :(得分:14)

你的理解是错误的。例如,b是一个指针 - 如果您想要new创建的对象的地址,则需要打印b,而不是&bb是一个局部变量,因此它本身(在&b处找到)位于堆栈中。

对于您的示例,Nlm可能位于可执行文件数据部分的某个位置。如您所见,它们具有相似的地址。您打印的每个其他变量都在堆栈中 - 它们的地址同样相似。其中一些是指向从堆分配的对象的指针,但没有一个打印输出会显示。

答案 1 :(得分:3)

您的理解是正确的。

  • 局部变量在堆栈上分配。
  • 动态分配的对象在堆上分配。

虽然您在示例中始终采用局部变量的地址 示例:打印d而不是d的地址。由于d是局部变量(因此地址类似于c),但它是指向动态分配的对象(that is on the heap)的指针变量。

编译器如何实现堆栈和堆栈会有所不同。

在现代操作系统中,堆栈和堆甚至可以共享相同的区域(即,您可以通过在堆中分配块来实现堆栈)。

答案 2 :(得分:2)

如果要打印任何d点的地址(在这种情况下它指向堆上的对象),请执行

  cout << "d: " << d << endl;

这将打印指针的值,指针的值是它指向的对象的地址。

您的代码

   cout << "&d: " << &d << endl;

这会打印d的地址,正如您在main中定义的d,它将在堆栈中,您打印指针的地址。有指针本身,它指向的对象,它们是2个单独的东西,有单独的地址。

答案 3 :(得分:2)

在您的示例中,唯一不在一起的是lmN。它们是两个静态和一个全局,因此它们不会在堆栈中分配。它们不是来自堆,最有可能的是,它们来自模块的.data段。堆中唯一的一个应该是地址b指向的地址,但是您打印的是b本身的地址,而不是它指向的地址。

答案 4 :(得分:0)

从纯C ++的角度来看,两种形式之间的区别仅在于如何管理对象的生命周期。

From here, good read

答案 5 :(得分:0)

静态变量位于数据段中。您还混合了指针的地址和它的值。例如a:

a是堆栈上类型A *的局部变量。 &amp; a还给出了一个地址(在堆栈上)。 a的值是类型A的堆对象的地址;

答案 6 :(得分:0)

你不能依赖各种编译器以同样的方式做事。对于几乎每一段代码,你都会写出堆栈和堆之间的区别是没有意义的。别担心。

答案 7 :(得分:0)

有些人可能无法安全地假设堆栈中相对于堆上的内容的相对地址,也就是说,不是所有指针的相对地址都是从同一个数组派生或分配的(通过malloc) ,calloc等)块。我甚至不确定指针是否必须是可排名的。