1. 错误
c语言函数返回局部变量地址。
2. 分析
c语言函数是不能返回局部变量地址(特指存放于栈区的局部变量地址),除非是局部静态变量地址,字符串常量地址、动态分配地址。其原因是一般局部变量的作用域只在函数内,其存储位置在栈区中,当程序调用完函数后,局部变量会随此函数一起被释放。其地址指向的内容不明(原先的数值可能不变,也可能改变)。而局部静态变量地址和字符串常量地址存放在数据区,动态分配地址存放在堆区,函数运行结束后只会释放栈区的内容,而不会改变数据区和堆区。
3. 错误实例
#include "stdio.h"
//返回局部变量a的地址
int* f1()
{
int a = 9;
int *pa = &a;
printf("a = %d\t&a = %p \n",a, &a);
printf("*pa = %d\tpa = %p \n",*pa, pa);
return pa;
}
int main()
{
int b = 5;
int *pb = &b;
printf("before: b = %d\t&b = %p\n",b, &b);
printf("before: *pb = %d\tpb = %p\n",*pb, pb);
pb = f1();
//printf("after : b = %d\t&b = %p\n",b, &b);
printf("after : *pb = %d\tpb = %p\n",*pb, pb);
return 1;
}
#include "stdio.h"
//返回局部变量a的地址
int* f1()
{
int a = 9;
int *pa = &a;
printf("a = %d\t&a = %p \n",a, &a);
printf("*pa = %d\tpa = %p \n",*pa, pa);
return pa;
}
int main()
{
int b = 5;
int *pb = &b;
printf("before: b = %d\t&b = %p\n",b, &b);
printf("before: *pb = %d\tpb = %p\n",*pb, pb);
pb = f1();
printf("after : b = %d\t&b = %p\n",b, &b);
printf("after : *pb = %d\tpb = %p\n",*pb, pb);
return 1;
}
如上2个实例便是在函数中返回局部变量地址。其中第1个例子直接输出*pb,其结果是对的。但若像第2个例子一样,在输出前添加如下语句:
printf(“after : b = %d\t&b = %p\n”,b, &b);
其结果是错误的,因为此语句修改栈区内容。所以返回局部变量地址,其结果可能正确,也可能错误,这取决于函数之后的代码是否使用并修改栈区内容。而计算机编程必须确保程序执行正确性和唯一性,任何不确定的运行结果都是错误的。
4. 正确实例
4.1 正确实例1
提示:静态变量用static修饰。
#include "stdio.h"
//返回静态局部变量a的地址
int* f1()
{
static int a = 9;
int *pa = &a;
printf("a = %d\t&a = %p \n",a, &a);
printf("*pa = %d\tpa = %p \n",*pa, pa);
return pa;
}
int main()
{
int b = 5;
int *pb = &b;
printf("before: b = %d\t&b = %p\n",b, &b);
printf("before: *pb = %d\tpb = %p\n",*pb, pb);
pb = f1();
printf("after : b = %d\t&b = %p\n",b, &b);
printf("after : *pb = %d\tpb = %p\n",*pb, pb);
return 1;
}
4.2 正确实例2
注意:
char *pa = "abc";
对于如上代码,pa指向的是字符串常量"abc"。
char a[] = "abc";
char *pa = a;
对于如上代码,pa指向的是字符串变量a。
#include "stdio.h"
//返回字符串常量的地址
char* f1()
{
int a = 9;
char *pa = "abc";
printf("a = %d\t&a = %p \n",a, &a);
printf("*pa = %d\tpa = %p \n",*pa, pa);
return pa;
}
int main()
{
int b = 5;
char *pb = "b";
printf("before: b = %d\t&b = %p\n",b, &b);
printf("before: *pb = %d\tpb = %p\n",*pb, pb);
pb = f1();
printf("after: b = %d\t&b = %p\n",b, &b);
printf("after : *pb = %d\tpb = %p\n",*pb, pb);
return 1;
}
4.3 正确实例3
提示:malloc用于手动的动态分配内存。
#include "stdio.h"
#include "stdlib.h"
//返回动态分配的地址
int* f1()
{
int a = 9;
int *pa = (int*) malloc(8);
*pa = a;
printf("a = %d\t&a = %p \n",a, &a);
printf("*pa = %d\tpa = %p \n",*pa, pa);
return pa;
}
int main()
{
int b = 5;
int *pb = &b;
printf("before: b = %d\t&b = %p\n",b, &b);
printf("before: *pb = %d\tpb = %p\n",*pb, pb);
pb = f1();
printf("before: b = %d\t&b = %p\n",b, &b);
printf("after : *pb = %d\tpb = %p\n",*pb, pb);
return 1;
}
5. 总结
从如上3个实例可看出,返回静态局部变量地址、返回字符串常量地址和返回动态分配地址,其结果都是正确的。这是因为以上地址指向的内容都不在栈区中,即使释放函数,其内容也不受影响。