在每次循环迭代中,一次又一次地声明变量j.那为什么它的地址保持不变?
- 不应该每次都给它一些随机地址吗?
- 这个编译器是否依赖?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i=3;
while (i--)
{
int j;
printf("%p\n", &j);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
测试运行:-
shadyabhi@shadyabhi-desktop:~/c$ gcc test.c
shadyabhi@shadyabhi-desktop:~/c$ ./a.out
0x7fffc0b8e138
0x7fffc0b8e138
0x7fffc0b8e138
shadyabhi@shadyabhi-desktop:~/c$
Run Code Online (Sandbox Code Playgroud)
Mar*_*ins 12
它是堆栈中的内存.它不是从堆中分配的.堆栈在该循环中不会改变.
j
永不改变地址的原因是因为编译器j
在输入函数时为堆栈分配内存而不是j
进入作用域时.
与往常一样,查看一些汇编代码可能有助于解释这个概念.采取以下功能: -
int foo(void)
{
int i=3;
i++;
{
int j=2;
i=j;
}
return i;
}
Run Code Online (Sandbox Code Playgroud)
gcc将其转换为以下x86汇编代码: -
foo:
pushl %ebp ; save stack base pointer
movl %esp, %ebp ; set base pointer to old top of stack
subl $8, %esp ; allocate memory for local variables
movl $3, -4(%ebp) ; initialize i
leal -4(%ebp), %eax ; move address of i into eax
incl (%eax) ; increment i by 1
movl $2, -8(%ebp) ; initialize j
movl -8(%ebp), %eax ; move j into accumulator
movl %eax, -4(%ebp) ; set i to j
movl -4(%ebp), %eax ; set the value of i as the function return value
leave ; restore stack pointers
ret ; return to caller
Run Code Online (Sandbox Code Playgroud)
让我们来看看这个汇编代码.第一行保存当前堆栈基指针,以便在函数退出时可以恢复,第二行将堆栈的当前顶部设置为此函数的新堆栈基指针.
第三行是为堆栈分配所有局部变量的内存.该指令subl $8, %esp
从堆栈指针的当前顶部(esp
寄存器)中减去8 .堆栈在内存中增长,因此这行代码实际上将堆栈上的内存增加了8个字节.我们在这个函数的两个整数,i
并且j
,每个需要4个字节,因此为什么它分配8个字节.
第4行i
通过直接写入堆栈上的地址初始化为3.然后第5行和第6行加载并递增i
.第7行j
通过将值2写入j
堆栈中分配的内存来初始化.请注意,当j
进入第7行的范围时,汇编代码没有调整堆栈来为它分配内存,这已经在之前得到了解决.
我确信它很明显,但是编译器在函数开始时为所有局部变量分配内存的原因是因为这样做更有效.每次局部变量进入或超出范围时调整堆栈将导致对堆栈指针进行大量不必要的操作而无法获得增益.
我相信你可以弄清楚其余的汇编代码自己做了什么,如果不发表评论,我会引导你完成它.
归档时间: |
|
查看次数: |
362 次 |
最近记录: |