当一个函数执行完后,内部的局部变量会被销毁,因此,在返回函数值时,不要返回局部变量,否则会出现不知名的错误。但是,有的时候又是可以返回局部变量的,这又是为什么呢?
来看一下这个例子:
假如定义了一个如下的结构:
struct LIST{
int a;
int b;
};
定义一个函数:
struct LIST make1(int x, int y){
struct LIST temp;
temp.a = x;
temp.b = y;
return temp;
}
使用如下语句进行赋值:
Int *p = make(1,2);
运行结果如图:
结果正确!!! 不是说不能返回局部变量吗?为什么这里能得到正确的结果呢?
仔细分析,我们发现,虽然函数make1里的temp是局部变量,将随着make1的结束而撤销,但是在make1结束时,temp里面的数据已经作为函数值返回了,与temp的撤销无关。因此,如果只是返回值的话,即使返回局部变量,那么最终还是会将正确的值传到相应的变量。再看下面一个例子:
char *func(){
char a[] = "1234";
return a;
}
char *p;
p = func();
printf("%s", p);
运行结果:
输出的与a数组中的字符串完全不一样!!! 因为数组作为局部变量,当函数结束后,数组便被销毁。
int *func(){
int a = 2;
return &a;
}
int *p;
p = func();
printf("%d\n", *p);
运行结果是
!!!仍然是2 !!!不是说内部变量会被销毁吗?为什么p指向地址存储的值还是2!!!
原来编译器在函数执行结束后,的确会对局部变量进行销毁,但是需要一定的时间。例如以下代码:
最终,运行的结果是:
结果正确。
下面再看一个例子:
struct LIST *make2(int x, int y){
struct LIST *temp;
temp = (struct LIST*)malloc(sizeof(struct LIST));
temp->a = x;
temp->b = y;
printf("变?量?内ú部?地?址·%ox\n",temp);
printf("变?量?内ú部?地?址·%ox %ox\n",&temp->a, &temp->b);
printf("变?量?在ú内ú部?地?址·的?值μ:阰%d %d",*(&temp->a),*(&(temp->b)));
return temp;
}
struct LIST *p = make2(1,2);
printf("\n变?量?外猘部?地?址·:阰%ox\n", p);
printf("变?量?在ú内ú部?地?址·的?值μ:阰%d %d\n",*(&p->a),*(&(p->b)));
printf("%d %d\n", p->a, p->b);
执行结果为:
在函数里面定义了局部指针,但最终的值还是不变!!!这又是为什么呢?
原来,有malloc申请的内存是存放在堆中,因此,在函数结束后并不会被销毁!!!
现在复习一下C语言中变量的存储地址分配。
存储区可以分为:
- 代码区:用来存放程序的二进制代码
- 文字常量区:存放字符串常量
- 全局区(静态区):用来存放全局变量和静态变量
- 堆:一般由程序员分配和释放。
- 栈:编译器自动分配和释放,存放函数的参数,局部变量等。