这是我在回复CSDN的C版区一个问临时变量问题的回复内容。以前也看到很多类似的问题,这次写了几句简单的代码,测试后算作一个总结吧!
#include <stdio.h>
2 static int num = 10;
3 static int *add = NULL;
4 int get_value()
5 {
6 int temp = num;
//嵌入汇编语言,咱把局部变量的地址取出来,然后在外部使用
7 __asm__ volatile(
8 "movl %%ebp, %%edx\n\t"
9 "subl $0x4, %%edx\n\t"
10 :"=d"(add)
11 :);
12 return temp;
13 }
14 int main()
15 {
16 int i;
17
18 get_value();//获取结果为10,标志获取临时变量temp地址成功
19 printf("1 old value:%d\n", *add);
20 *add = 30;//我们使用这个临时变量,是可以使用的,得到30
21 printf("new value:%d\n", *add);
22 i = get_value();
23 printf("return value:%d\n", i);
printf("2 old value:%d\n", *add); //2次调用后,结果又刷回到10
24 return 0;
25 }
下面是gcc 4.6.3编译后并反汇编的结果,主函数就不帖了,无关紧要
080483e4 <get_value>:
124 80483e4: 55 push %ebp
125 80483e5: 89 e5 mov %esp,%ebp
126 80483e7: 83 ec 10 sub $0x10,%esp
127 80483ea: a1 14 a0 04 08 mov 0x804a014,%eax
128 80483ef: 89 45 fc mov %eax,-0x4(%ebp)
129 80483f2: 89 ea mov %ebp,%edx//这4句是我加的内容,得到%ebp-0x4地址,因为整数占4B(32bit)
130 80483f4: 83 ea 04 sub $0x4,%edx
131 80483f7: 89 d0 mov %edx,%eax
132 80483f9: a3 20 a0 04 08 mov %eax,0x804a020
133 80483fe: 8b 45 fc mov -0x4(%ebp),%eax
134 8048401: c9 leave
135 8048402: c3 ret
当然如果嵌入汇编不好理解,你可以直接取地址,像这样
int get_value()
5 {
6 int temp = num;
12 add = &temp;
13 return temp;
14 }
效果是一样的
我这样做并不是鼓励去使用或者引用临时变量,而是要清楚几点:
1. 内存在函数调用的表达式结束后就回收了. 回收并不代表内存就不可用了. 内存还在.这里的回收意思可作为空闲区由系统分配。(比如我在主函数里使用它)
2. 函数的局部变量内存是在栈里面的, 不在文件的Data段.(mov %esp,%ebp可证明)
3. 临时变量生命期由函数的返回,弹出栈操作回到调用函数,而让用户不再拥有看到局部变量的地址而算作“消亡”。其实这点算作第1点的补充,所以“消亡”要加引号。
4. 记住不要在外使用“消亡”的临时变量,否则,只会造成潜在的bug!