#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main() {
for(int i=0;i<5;++i)
{
int x=i;
cout<<&x<<endl;
}
}
теперь каждый раз он печатает один и тот же адрес памяти. Теперь x уничтожается после каждой итерации как единственной локальной переменной. Но почему тогда адрес x всегда один и тот же?
Мы можем посмотреть на разборку этой программы, чтобы понять, что происходит. Перед запуском мы можем немного упростить его, заменив cout, endl - >> printf. Нет ничего особенного, но разобранная петля будет немного короче.
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main() {
for(int i=0;i<5;++i)
{
int x=i;
printf("%x\n",&x);
}
}
Построить g++ -o main main.c
, запустить ./main
, дизассемблировать с objdump -d main
, основной дизассемблировать с комментариями (значимые строки отмечены "<< -", удаляются машинные коды команд):
0000000000400810 <main>:
400810: push %rbp ; prologue
400811: mov %rsp,%rbp ; --------
400814: sub $0x10,%rsp ; <<-- Prepare place at stack
; for two 4-byte variables!
; Addr. space: 0x4 + 0x4 = 0x10
400818: movl $0x0,-0x4(%rbp) ; init i with a 0
40081f: jmp 400841 <main+0x31> ; start loop -------------------.
400821: mov -0x4(%rbp),%eax ; <<-- move i to eax <----------|-.
400824: mov %eax,-0x8(%rbp) ; <<-- move eax to x | |
400827: lea -0x8(%rbp),%rax ; <<-- load effective | |
; address of x to rax | |
40082b: mov %rax,%rsi ; param - address of x | |
40082e: mov $0x400940,%edi ; param - address of format str | |
400833: mov $0x0,%eax ; param - final zero | |
400838: callq 4006a0 <printf@plt>; call printf(..) | |
40083d: addl $0x1,-0x4(%rbp) ; increment i | |
400841: cmpl $0x4,-0x4(%rbp) ; compare with 4 <----------' |
400845: jle 400821 <main+0x11> ; if <= go to --------------------'
400847: mov $0x0,%eax ; default return value
40084c: jmp 400856 <main+0x46>
40084e: mov %rax,%rdi
400851: callq 400710 <_Unwind_Resume@plt>
400856: leaveq
400857: retq
Поэтому компилятор просто перемещает x
за пределы цикла и удерживает его в стеке. Таким образом, мы имеем постоянный адрес x
. Протестировано на x86_64 с помощью соглашения об использовании ABI с системой V AMD64.
Это может быть компилятор. Он разработан с оптимизационными функциями. Вы должны проверить код выхода компилятора, чтобы понять, почему это так.
Каждый x повторно использует то же пространство памяти, что и старый x, из предыдущей итерации, поскольку старый ему больше не нужен :)