Адрес стека и кучи в 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 и т. д.) блок. Я даже не уверен, что указатели должны быть ранжируемыми.