前些日子,在QQ群里面,发现一些朋友在讨论函数返回后,为什么值可以传递和地址传递的情况;我也感到很好奇,
于是就跟了一下。
int* sum(int x,int y) { int a; a=x|y; return &a; }
很显然这段代码,存在一些问题;但是在VC2008中编译一切正常,运行状态也一切正常。
下面是我的测试代码:
#include <stdio.h> int* sum(int x,int y) { int a; a=x+y; return &a; } int getsum(int x,int y) { return x+y; } int main(void) { int *x; int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); a=getsum(1,2); x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); *x=100; printf("*x=%d; x=%u\n",*x,x); getchar(); return 0; }
运行结果如下所示:
这个就是运行的结果?但是为什么呢? 而且两次调用sum函数返回的地址完全一样。
为了测试,我决定将代码再进行异常改动。
#include <stdio.h> int* sum(int x,int y) { int a; a=x+y; return &a; } int getsum(int x,int y) { int* p; p=sum(10,2); printf("*x=%d; x=%u\n",*p,p); return *p; } int main(void) { int *x; int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); a=getsum(1,2); x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); *x=100; printf("*x=%d; x=%u\n",*x,x); getchar(); return 0; }
代码依然坚挺的活着,而且顺利的运行,如下所示,只是在getsum里面调用sum函数,得到的地址与main函数中得到的不一样。
而且可以发现,无论怎么调用,在main函数中调用sum,返回的地址一直是一样的? 这是怎么回事呢?
如果是这样的话,那么是否可以用这种方法动态分配地址呢? 是否可以我们free 一下看看。很不幸的是,失败了?
提示:可能是heap——栈——异常中断了程序。
为什么会这样呢?
原因可能是:
1、C程序在运行的过程中,其地址空间是固定的;虽然是可重定向的,但是在“他”自己的线性空间,其地址空间是固定的,
也就是所函数调用的压栈的空间,其栈基址是固定的。
2、由于压栈顺序是一致的,而且每次压栈时变量的offset是一定的。从左往右压栈,或者从右往左压栈都一样会得到这个结果。
因此就出现了上面的情况。
那么怎样说明这个过程的不正常呢? 虽然他看起来能编译、链接和运行,结果也很正常。
#include <stdio.h> int *x; int* sum(int x,int y) { int a; a=x+y; return &a; } void getsum() { x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第二个输出 } int main(void) { int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第一个输出 getsum(); printf("*x=%d; x=%u\n",*x,x); //第三个输出 *x=100; printf("*x=%d; x=%u\n",*x,x); //第四个输出
getchar(); return 0; }
可以发现,第一个输出,第二输出的 *x的值一样; 而第二个、第三个、第四个则是x的只一样。这又是为什么呢?
我们在改一下:
#include <stdio.h
int *x; int* sum(int x,int y) { int a; a=x+y; return &a; }
void getsum() { x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第二个输出 } int main(void) { int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第一个输出 getsum(); printf("*x=%d; x=%u\n",*x,x); //第三个输出 *x=100; printf("*x=%d; x=%u\n",*x,x); //第四个输出 x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第五个输出 getchar(); return 0; }
又或者这样测试一下:
#include <stdio.h> int *x; int* sum(int x,int y) { int a; a=x+y; return &a; } int* sum1(int x,int y) { int a; a=x+y; return &a; } void getsum() { x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第二个输出 } int main(void) { int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第一个输出 getsum(); printf("*x=%d; x=%u\n",*x,x); //第三个输出 *x=100; printf("*x=%d; x=%u\n",*x,x); //第四个输出 x=sum1(10,2); printf("*x=%d; x=%u\n",*x,x); //第五个输出 getchar(); return 0; }
我们再改一下:
#include <stdio.h> int *x; int* sum(int x,int y) { int a; a=x+y; return &a; } int* sum1(int c,int d) { int a; a=c+d; *x=60; return x; } void getsum() { x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第二个输出 } int main(void) { int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第一个输出 getsum(); printf("*x=%d; x=%u\n",*x,x); //第三个输出 *x=100; printf("*x=%d; x=%u\n",*x,x); //第四个输出 x=sum1(10,2); printf("*x=%d; x=%u\n",*x,x); //第五个输出 getchar(); return 0; }
输出结果如下所示:
发现x的地址可以一直引用。
如果你要做一些坏事的话,这里就是一个可以利用的地方。 可以通过这个全局的x变量,来修改传递给函数的参数值。
这个实验就不做了。
有兴趣的可以试一下。