zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C语言指向堆和栈指针分析(四十九)

C语言 分析 指针 指向
2023-09-14 09:09:58 时间

结论:函数可以返回局部变量的值,但是不能返回指向栈内存的指针。
原因:

局部变量的作用域为函数内部函数执行结束操作系统会自动释放栈上的局部变量并且函数返回的是局部变量的值拷贝

  但是如果返回局部变量的地址,那么返回的是该局部变量地址的值拷贝,但是函数运行结束,该拷贝指针所指向的栈内容已经被释放即为野指针,对野指针所指向内容的操作都会造成段错误.
函数是可以返回指向堆内存的指针,但是这需要在调用者在函数外手动进行内存的释放,可以通过指针传递来解决。

一般来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。

因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。

  总结如下: 

  (1)返回指向字符串常量的指针

  (2)不能返回以局部变量方式创建的字符串数组首地址

  (3)在函数中,允许返回局部变量的值,不允许返回局部变量的地址

  (4)在函数中,如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。

  (5)数组是不能作为函数的返回值

  (6)返回指向堆内存的指针是可以的

#include <iostream>
#include <stack>
#include <string.h>
using namespace std;

int fun0(){
	int cc = 5; //在栈上分配内存
   //可以返回局部变量,因为返回的是cc是拷贝一份的值,fun0()函数结束后,cc释放掉,副本值可以返回正确的值.
	return cc;
}

int* fun(){
	int cc = 5;//在栈上分配内存
   //返回cc的地址,fun()函数结束时,cc在栈上分配的内存会出栈,释放掉,这时返回的地址是一个野指针 
	return &cc;
}

int* fun1(){
	int cc = 5;
	int *p = &cc;
	return p;
}

int* fun2(){
	int cc = 66;//在栈上分配内存
	int *p = &cc;	
	return p;//返回cc的地址,fun()函数结束时,cc在栈上分配的内存会出栈,释放掉,这时返回的地址是一个野指针 
}

int main(){
    //OK
    int cc = fun0();
	printf("%d\n", cc);

	//Error
	int *m = fun();
	printf("%d\n", *m);
	
#if 0
	//way 1:OK;这里虽然是正确的,但是下面的栗子确实错误的,概率问题,不能返回局部变量的指针
	int *p = fun1();
	printf("%d\n", *p);

	int *q = fun2();
	printf("%d\n", *q);
	
#else

	//way 2:Error ;可能分配堆栈顺序问题,返回结果都是66
	int *p = fun1();
	int *q = fun2();
	printf("%d\n", *p);
	printf("%d\n", *q);
#endif
	
	return 0;   
}
总结:不能返回局部变量的指针是有前提的:
1.可以返回指针指向全局变量、堆上分配(new,malloc)、常量区(如:"123")、静态区(static)的指针
2.不能返回指向栈的指针,因为栈随函数执行完成,出栈自动回收内存,会造成指向的是一个无效地址,导致段错误