Адрес стека и кучи в 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 ответов


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

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


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

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

хотя вы последовательно берете адрес локальной переменной в своем примере.
Пример: распечатать d Не адрес d. As d является локальной переменной (поэтому адрес похож на c), но это переменная указатель на динамически выделенный объект (that is on the heap).

как компилятор реализует стек и кучу, хотя будет отличаться.

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


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


если вы хотите напечатать адрес whatever d указывает на (в этом случае он указывает на объект в куче), do

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

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

ваш код

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

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


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

отсюда, хорошо читать


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

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


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


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