返回局部变量 、局部指针、 局部数组
这三种情况,
那些是正确的,那些是错误的容易出问题的?
我已经知道返回局部指针不正确,但如果局部指针指向静态区常量还是不会出错的。
但是返回局部变量 和 返回局部数组还不清楚。
希望有深度的回答。
25 个解决方案
#1
返回局部变量,其实是拷贝的副本,所以没问题。
返回局部指针,指针指向的内容会随函数失效,所以不妥。
返回局部数组,你想用什么语法返回?一般没试过返回数组。
返回局部指针,指针指向的内容会随函数失效,所以不妥。
返回局部数组,你想用什么语法返回?一般没试过返回数组。
#2
局部变量:如果是基本变量,可以直接返回;如果是自定义变量,基本都是使用指针参数带出。
局部指针:如果指针指向的内存是在函数内部申请的,基本不干返回指针这种事,做这种事情很有可能是在给自己找麻烦,多数做的都是在可以释放的地方申请好内存,通过指针传递进函数,申请和释放都在同一函数中。
局部数组:我相信没什么人想返回这个东西。
int Sum( int a, int b ) // 基本变量没什么问题。
{
return (a+b);
}
int DoSomething( const struct MyStruct * pParamIn1, const struct MyStruct * pParamIn2, strct MyStruct * pParamOut )
{
// 在这里处理pParamIn1和pParamIn2指向的结构体,将结果保存到pParamOut指向的结构体中
// 带出函数,返回值只表示函数处理成功还是失败以及可能的失败原因
}
局部指针:如果指针指向的内存是在函数内部申请的,基本不干返回指针这种事,做这种事情很有可能是在给自己找麻烦,多数做的都是在可以释放的地方申请好内存,通过指针传递进函数,申请和释放都在同一函数中。
void ToBeCalledByFun( SomeType * pParam ) // 被调用函数不申请堆内存
{
// Do something to *pParam
}
void Fun( /*some parameters*/ )
{
SomeType * pCallMem = (SomeType *)malloc( sizeof(SomeType) );
// 内存申请放在free的同一个函数里
ToBeCalledByFun( pCallMem );
// Do something
free( pCallMem );
pCallMem = NULL;
}
局部数组:我相信没什么人想返回这个东西。
#3
局部指针的话,通常人都认为指向的局部变量失效,那该地址存的是垃圾值,其实不然,系统要在接到你要操作这个内存的指令后才会把它清0,它并不是立刻清0,就好比文件一样,并不是接到指令立刻把文件全清0,只是标记告诉系统这个空间可用,文件一般是在的。
数组也是一样,下面有个小实例,第一个能正常输入,第二个则不行,因为在它之前操作了这块内存,操作了这块内存。
数组也是一样,下面有个小实例,第一个能正常输入,第二个则不行,因为在它之前操作了这块内存,操作了这块内存。
#include "stdafx.h"
char * Cstr(void)
{
char a[10] = "like";
return a;
}
int main(void)
{
char *a=Cstr();
printf("%c\n",*(a+1));
printf("%c\n",*(a+1));
return 0;
}
#4
上面是输出,打错个字。
#5
局部变量的返回是值传递,这个是没有问题的
局部指针不必说
局部数组返回是不可以的,因为数组是一片连续的内存区域,如果是局部数组,那就是在栈上分配,而在这里数组名和指针是一样的,函数返回后,内存空间就会被回收
局部指针不必说
局部数组返回是不可以的,因为数组是一片连续的内存区域,如果是局部数组,那就是在栈上分配,而在这里数组名和指针是一样的,函数返回后,内存空间就会被回收
#6
你说的返回局部数组就考虑了,不知道你怎么返回的
考虑返回局部变量和局部变量指针
return语句
调用函数的时候,会在调用函数的地方生成一个临时变量,return语句将你要的返回值赋给这个临时变量,也就是临时变量得到返回值的一个副本
其实很简单,如果指针指向的是一段栈区(局部变量就放在这里啦),函数结束后返回,这段栈被释放了,你能通过return得到指针的副本,但是这是指针指向的空间已经无效啦,你让指针咋办呢?
对比局部变量,返回它,就是让上面说的临时变量得到它的一个副本嘛,然后你想对这个副本干嘛就干嘛咯
#7
局部变量里面还得分为自动还是静态,两者结果是不同的,得分开描述。
数组是不能作为函数的返回值的,原因是数组名是一个不可修改的左值,例如这样的代码是非法的:
int func( void )[5];
返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。例如:
int* func( void )
{
static int a[10];
........
return a;
}
局部变量也*部自动变量和局部静态变量,由于c返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,因为这时候返回的是这个局部变量的值,但不应该返回指向局部自动变量的指针,因为函数调用结束后该局部自动变量被抛弃,这个指针指向一个不再存在的对象,是无意义的。但可以返回指向局部静态变量的指针,因为静态变量的生存期从定义起到程序结束。例如:
int func()
{
int a;
....
return a; //允许
}
int * func()
{
int a;
....
return &a; //无意义,不应该这样做
}
局部指针跟上面所述的局部变量一样。可以返回一个局部指针的值,也可以返回一个局部静态指针的地址,但不应该返回一个局部自动指针的地址。
#8
学习
#9
复议!
#10
局部变量:如果是值上的返回,没问题.
局部指针:和指针的指向有关.
局部数组:不能返回数组的.
局部指针:和指针的指向有关.
局部数组:不能返回数组的.
#11
说的很好啊
整个return机制就大概这么多吧,不知还有人知道return还能返回什么其他的类型吗?
整个return机制就大概这么多吧,不知还有人知道return还能返回什么其他的类型吗?
#12
UP
#13
总之,条款里说:禁止返回局部变量的指针或引用。
是有道理的
是有道理的
#14
这还要分情况讨论,例如局部指针:
是有问题的,如果这样:
在用的时候这样:
就没有问题
int * func(void)
{
int i = 10;
int * p = &i;
return p;
}
是有问题的,如果这样:
int * func(void)
{
int * p = molloc(10 * sizeof(int));
return p;
}
在用的时候这样:
int * q = func();
//...
free(q);
就没有问题
#15
条例说的没错,但是如果返回的是堆上的局部指针,而不是栈上的,就没有问题,当然,在这种情况下,一定要记得释放内存。
#16
条例说的没错,但是如果返回的是堆上的局部指针,而不是栈上的,就没有问题,当然,在这种情况下,一定要记得释放内存。
返回的是堆上的局部指针
也是不好的写法,这种情况其实你需要智能指针。
返回的是堆上的局部指针
也是不好的写法,这种情况其实你需要智能指针。
#17
上面各位说的很好了,我就提一点,其实这些都是关于变量的生存周期和变量作用域的问题。
#18
我觉得这个主要是要了解一下变量、参数的作用域的问题,以及参数是如何传递的问题。
在C专家编程里面有比较详细的说明
在C专家编程里面有比较详细的说明
#19
这个哥们说的好!只是书面了一些。你喜欢深的看下面
我来深一点!
return?什么叫return?程序原本是没有return的,自从有了C这样的高级语言后才有return这种形式。
是形式,真正实现还是汇编。对应寄存器eax !!(x86体系)
那么什么样的东西可以return呢?返回局部变量 、局部指针、 局部数组。。。。
只要是你在后边能够正常访问的东西即可,text,data中的持久数据肯定是可以的。那么stack中的呢?这要看你的程序返回后stack是否还有效?如果操作系统或者你自己的系统,在程序返回后不主动清空stack,那么你完全可以使用它。
C的美丽就在于直接操作内存和cpu,从机器运行本质看问题。一切问题都不是问题。
#20
上面说的虽然深入,但抽象了点,:)
下面针对这位哥们的深入,希望能够浅出!
副本:(非山口山副本!)
用深入的概念讨论一下副本,
int test()
{
......
int i=3;
return i;//这里返回i的副本
}
对应汇编: 手头没有编译器,随便写,意思意思
__test:
push
mv eax 3 ;这里返回i的副本
pop
ret
所谓的”返回 i 这个局部变量的副本“,其实就是他的值3放到exa中。
语言表达能力欠缺,希望大家能够明白我的意思。
#21
建议楼主读一下
《C专家编程》
然后你就会豁然开朗了!
这个问题是C比较深入的东西了,
一言难尽啊
#22
很多很好很强大的回复
谢谢各位
谢谢各位
#23
学习学习~~~~
#24
Agree with layer7, 10, 14, 19
#25
可不可以这么个理解呢?return返回了指针指向的堆空间的副本,而指针却是在栈中的,你没有把他给释放掉,所以这个指针还仍可以访问这段堆内存内的值;而如果是返回数组名的话应该也是如此,只不过你返回的是局部变量,在堆中会被很快释放掉(用完就被释放);
#1
返回局部变量,其实是拷贝的副本,所以没问题。
返回局部指针,指针指向的内容会随函数失效,所以不妥。
返回局部数组,你想用什么语法返回?一般没试过返回数组。
返回局部指针,指针指向的内容会随函数失效,所以不妥。
返回局部数组,你想用什么语法返回?一般没试过返回数组。
#2
局部变量:如果是基本变量,可以直接返回;如果是自定义变量,基本都是使用指针参数带出。
局部指针:如果指针指向的内存是在函数内部申请的,基本不干返回指针这种事,做这种事情很有可能是在给自己找麻烦,多数做的都是在可以释放的地方申请好内存,通过指针传递进函数,申请和释放都在同一函数中。
局部数组:我相信没什么人想返回这个东西。
int Sum( int a, int b ) // 基本变量没什么问题。
{
return (a+b);
}
int DoSomething( const struct MyStruct * pParamIn1, const struct MyStruct * pParamIn2, strct MyStruct * pParamOut )
{
// 在这里处理pParamIn1和pParamIn2指向的结构体,将结果保存到pParamOut指向的结构体中
// 带出函数,返回值只表示函数处理成功还是失败以及可能的失败原因
}
局部指针:如果指针指向的内存是在函数内部申请的,基本不干返回指针这种事,做这种事情很有可能是在给自己找麻烦,多数做的都是在可以释放的地方申请好内存,通过指针传递进函数,申请和释放都在同一函数中。
void ToBeCalledByFun( SomeType * pParam ) // 被调用函数不申请堆内存
{
// Do something to *pParam
}
void Fun( /*some parameters*/ )
{
SomeType * pCallMem = (SomeType *)malloc( sizeof(SomeType) );
// 内存申请放在free的同一个函数里
ToBeCalledByFun( pCallMem );
// Do something
free( pCallMem );
pCallMem = NULL;
}
局部数组:我相信没什么人想返回这个东西。
#3
局部指针的话,通常人都认为指向的局部变量失效,那该地址存的是垃圾值,其实不然,系统要在接到你要操作这个内存的指令后才会把它清0,它并不是立刻清0,就好比文件一样,并不是接到指令立刻把文件全清0,只是标记告诉系统这个空间可用,文件一般是在的。
数组也是一样,下面有个小实例,第一个能正常输入,第二个则不行,因为在它之前操作了这块内存,操作了这块内存。
数组也是一样,下面有个小实例,第一个能正常输入,第二个则不行,因为在它之前操作了这块内存,操作了这块内存。
#include "stdafx.h"
char * Cstr(void)
{
char a[10] = "like";
return a;
}
int main(void)
{
char *a=Cstr();
printf("%c\n",*(a+1));
printf("%c\n",*(a+1));
return 0;
}
#4
上面是输出,打错个字。
#5
局部变量的返回是值传递,这个是没有问题的
局部指针不必说
局部数组返回是不可以的,因为数组是一片连续的内存区域,如果是局部数组,那就是在栈上分配,而在这里数组名和指针是一样的,函数返回后,内存空间就会被回收
局部指针不必说
局部数组返回是不可以的,因为数组是一片连续的内存区域,如果是局部数组,那就是在栈上分配,而在这里数组名和指针是一样的,函数返回后,内存空间就会被回收
#6
你说的返回局部数组就考虑了,不知道你怎么返回的
考虑返回局部变量和局部变量指针
return语句
调用函数的时候,会在调用函数的地方生成一个临时变量,return语句将你要的返回值赋给这个临时变量,也就是临时变量得到返回值的一个副本
其实很简单,如果指针指向的是一段栈区(局部变量就放在这里啦),函数结束后返回,这段栈被释放了,你能通过return得到指针的副本,但是这是指针指向的空间已经无效啦,你让指针咋办呢?
对比局部变量,返回它,就是让上面说的临时变量得到它的一个副本嘛,然后你想对这个副本干嘛就干嘛咯
#7
局部变量里面还得分为自动还是静态,两者结果是不同的,得分开描述。
数组是不能作为函数的返回值的,原因是数组名是一个不可修改的左值,例如这样的代码是非法的:
int func( void )[5];
返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。例如:
int* func( void )
{
static int a[10];
........
return a;
}
局部变量也*部自动变量和局部静态变量,由于c返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,因为这时候返回的是这个局部变量的值,但不应该返回指向局部自动变量的指针,因为函数调用结束后该局部自动变量被抛弃,这个指针指向一个不再存在的对象,是无意义的。但可以返回指向局部静态变量的指针,因为静态变量的生存期从定义起到程序结束。例如:
int func()
{
int a;
....
return a; //允许
}
int * func()
{
int a;
....
return &a; //无意义,不应该这样做
}
局部指针跟上面所述的局部变量一样。可以返回一个局部指针的值,也可以返回一个局部静态指针的地址,但不应该返回一个局部自动指针的地址。
#8
学习
#9
复议!
#10
局部变量:如果是值上的返回,没问题.
局部指针:和指针的指向有关.
局部数组:不能返回数组的.
局部指针:和指针的指向有关.
局部数组:不能返回数组的.
#11
说的很好啊
整个return机制就大概这么多吧,不知还有人知道return还能返回什么其他的类型吗?
整个return机制就大概这么多吧,不知还有人知道return还能返回什么其他的类型吗?
#12
UP
#13
总之,条款里说:禁止返回局部变量的指针或引用。
是有道理的
是有道理的
#14
这还要分情况讨论,例如局部指针:
是有问题的,如果这样:
在用的时候这样:
就没有问题
int * func(void)
{
int i = 10;
int * p = &i;
return p;
}
是有问题的,如果这样:
int * func(void)
{
int * p = molloc(10 * sizeof(int));
return p;
}
在用的时候这样:
int * q = func();
//...
free(q);
就没有问题
#15
条例说的没错,但是如果返回的是堆上的局部指针,而不是栈上的,就没有问题,当然,在这种情况下,一定要记得释放内存。
#16
条例说的没错,但是如果返回的是堆上的局部指针,而不是栈上的,就没有问题,当然,在这种情况下,一定要记得释放内存。
返回的是堆上的局部指针
也是不好的写法,这种情况其实你需要智能指针。
返回的是堆上的局部指针
也是不好的写法,这种情况其实你需要智能指针。
#17
上面各位说的很好了,我就提一点,其实这些都是关于变量的生存周期和变量作用域的问题。
#18
我觉得这个主要是要了解一下变量、参数的作用域的问题,以及参数是如何传递的问题。
在C专家编程里面有比较详细的说明
在C专家编程里面有比较详细的说明
#19
这个哥们说的好!只是书面了一些。你喜欢深的看下面
我来深一点!
return?什么叫return?程序原本是没有return的,自从有了C这样的高级语言后才有return这种形式。
是形式,真正实现还是汇编。对应寄存器eax !!(x86体系)
那么什么样的东西可以return呢?返回局部变量 、局部指针、 局部数组。。。。
只要是你在后边能够正常访问的东西即可,text,data中的持久数据肯定是可以的。那么stack中的呢?这要看你的程序返回后stack是否还有效?如果操作系统或者你自己的系统,在程序返回后不主动清空stack,那么你完全可以使用它。
C的美丽就在于直接操作内存和cpu,从机器运行本质看问题。一切问题都不是问题。
#20
上面说的虽然深入,但抽象了点,:)
下面针对这位哥们的深入,希望能够浅出!
副本:(非山口山副本!)
用深入的概念讨论一下副本,
int test()
{
......
int i=3;
return i;//这里返回i的副本
}
对应汇编: 手头没有编译器,随便写,意思意思
__test:
push
mv eax 3 ;这里返回i的副本
pop
ret
所谓的”返回 i 这个局部变量的副本“,其实就是他的值3放到exa中。
语言表达能力欠缺,希望大家能够明白我的意思。
#21
建议楼主读一下
《C专家编程》
然后你就会豁然开朗了!
这个问题是C比较深入的东西了,
一言难尽啊
#22
很多很好很强大的回复
谢谢各位
谢谢各位
#23
学习学习~~~~
#24
Agree with layer7, 10, 14, 19
#25
可不可以这么个理解呢?return返回了指针指向的堆空间的副本,而指针却是在栈中的,你没有把他给释放掉,所以这个指针还仍可以访问这段堆内存内的值;而如果是返回数组名的话应该也是如此,只不过你返回的是局部变量,在堆中会被很快释放掉(用完就被释放);