C语言错误:函数返回局部变量地址


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;
}

运行结果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

  如上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个实例可看出,返回静态局部变量地址、返回字符串常量地址和返回动态分配地址,其结果都是正确的。这是因为以上地址指向的内容都不在栈区中,即使释放函数,其内容也不受影响。

  • 12
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值