Адрес стека и кучи в C ++

Исправление:

Я перепутал с концепцией адреса указателя и адреса, на который указывает указатель, поэтому следующий код был изменен. И теперь он печатает, что я хочу, переменные 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, адреса всех остальных переменных кажутся вместе. (Примечание: код и результаты были изменены и не соответствуют тому, что здесь сказано.)

Я много искал о стеке и куче. Здравый смысл заключается в том, что, если объект создается «новым», то он находится в куче. А локальные переменные (такие как j и k в приведенном выше примере) находятся в стеке. Но, похоже, это не так в моем примере. Зависит ли это от разных компиляторов, или мое понимание неверно?

Большое спасибо всем вам.

8
задан Zhongxia Zhou 19 August 2010 в 20:55
поделиться

8 ответов

Ваше понимание неверно. Например, b является указателем - если вы хотите получить адрес объекта, созданного с помощью new , вам нужно вывести b , а не & b. . b - это локальная переменная, поэтому она сама (находится по адресу & b ) находится в стеке.

Для вашего примера, N , l и m предположительно где-то в разделе данных вашего исполняемого файла. Как видите, у них похожие адреса. Все остальные переменные, которые вы распечатываете, находятся в стеке - их адреса также похожи друг на друга. Некоторые из них являются указателями на объекты, выделенные из кучи, но ни одна из ваших распечаток этого не покажет.

15
ответ дан 5 December 2019 в 07:33
поделиться

Если вы хотите вывести адрес того, на что указывает d (в данном случае он указывает на объект на куче), сделайте

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

Это выведет значение указателя, а значение указателя - это адрес объекта, на который он указывает.

Ваш код имел

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

Это печатает адрес d, так как вы определили d внутри main, он будет на стеке, вы печатаете адрес указателя. Есть сам указатель и объект, на который он указывает, это две отдельные вещи, с отдельными адресами.

2
ответ дан 5 December 2019 в 07:33
поделиться

Ваше понимание правильное.

  • локальные переменные выделяются в стеке.
  • динамически выделяемые объекты выделяются в куче.

Хотя в своем примере вы последовательно берете адрес локальной переменной.
Пример: выведите d, а не адрес d. Так как d является локальной переменной (поэтому адрес похож на c), но это переменная-указатель, которая указывает на динамически выделенный объект (который находится на куче).

То, как компилятор реализует стек и кучу, может быть разным.

В современных ОС стек и куча могут даже разделять одну и ту же область (т.е. вы можете реализовать стек, выделяя куски в куче).

3
ответ дан 5 December 2019 в 07:33
поделиться

Единственные, которые не «вместе» в вашем примере, это l , m и N . Это две статические и одна глобальная, поэтому они точно не размещаются в стеке. Они тоже не из кучи, скорее всего, они из сегмента .data вашего модуля. Единственным адресом из кучи должен быть адрес, на который указывает b , но вы печатаете адрес самого b , а не того, на что он указывает.

2
ответ дан 5 December 2019 в 07:33
поделиться

Можно с уверенностью предположить, что что-либо об относительных адресах вещей в стеке относительно тех, что в куче, ни, если на то пошло, относительные адреса любых указателей, которые не все получены из одного и того же массива или выделены (через malloc, calloc и т. д.) блоком. Я даже не уверен, что указатели должны быть ранжируемыми.

0
ответ дан 5 December 2019 в 07:33
поделиться

Различие между этими двумя формами, с точки зрения чистого C++, связано только с тем, как управляется время жизни объектов.

Отсюда хорошее чтение

0
ответ дан 5 December 2019 в 07:33
поделиться

Статические переменные находятся в сегменте данных. Также вы смешиваете адрес указателя и его значение. Например, a:

a - это локальная переменная типа A* на стеке. &a также дает адрес, по которому a находится на самом деле (на стеке). Значение a - это адрес объекта кучи типа A;

0
ответ дан 5 December 2019 в 07:33
поделиться

Вы не можете полагаться на то, что различные компиляторы делают все одинаково. Почти для каждого куска кода, который вы напишете, различия между стеком и кучей не имеют смысла. Не беспокойтесь об этом.

0
ответ дан 5 December 2019 в 07:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: