关于函数返回值的问题[转]
我有一个程序是这样的: int main() { int *p; int i; int*fun(void); p=fun(); for(i=0;i<3;i++) { printf("%d\n",*p); p++; } return 0; }; int* fun(void) { static int str[]={1,2,3,4,5}; int*q=str; return q; } 我想问一下,除了将str定义为静态区以及用malloc这样的方法外,还有什么好的方法,同时也想问一下如果我改成 int main() { char *p; char*fun(void); p=fun(); printf("%s\n",p); return 0; }; char * fun(void) { char *str="hello"; return str; } 为什么能输出准确值,函数返回指针有哪些方法。
问题补充:
使用字符数组时,就能返回正确值 int main() { char *p; char *fun(void); p=fun(); printf("%c",p[2]); return 0; }; char* fun(void) { char str[]={'a','b','c'}; return str; } 但若将str[]改成str[]="hello"却不行。
满意回答
追问
这里我还是没太明白,比如: int main() { int a,b; int max; int fun (int a,int b); scanf("%d%d",&a,&b); max=fun (a,b); printf("\n%d\n",max); return 0; }; int fun(int a,int b) { int max; if(a>b) max=a; else max=b; return max; } 在这个程序,为什么在fun()函数中就能返回max,按照动态存储原理,在fun结束时,就max就被释放了,不能再返回值了。但事实却不是这样。
回答
这个例子中,返回的不是变量max的地址,返回的是它的值。 return后面的东西,看做一个表达式,返回的是这个表达式的值。 例如,入口如果a是3,b是5,则此时(执行return语句时)max里面存的是5。而return语句的功能就是把max里面的5取出来,放到“返回值寄存器”中。 主程序是从“返回值寄存器”得到这个5的(此时max变量已经不存在了)。 你前面的第二个例子中,同样,指针变量str在函数结束后已经不存在了。但是在return语句中,把指针变量str里面的值(等于字符串"hello"存放处的地址)送到“返回值寄存器”中了。 动态变量str不存在了,但常量区中的字符串"hello"还存在。主程序根据返回的地址就可以找到该字符串。
追问
返回的是值,这个我明白了,但还是有点不明白的是: int main() { char *p; char *fun(void); p=fun(); printf("%x\n",p); printf("%s\n",p); return 0; } char* fun(void) { // char str[]={'a','b','c','d','e','f','\0'}; char str[]="hello"; printf("%x\n",str); return str; } 返回的也是str的地址,从结果来看p和str的值相等,但为什么准确,我的qq是121814322,谢谢加我,希望继续请教。
回答
char str[]="hello"; 和 char *str="hello"; 不一样。 char str[]="hello"; 是在动态变量区中开辟了可以容纳6个字符的数组,数组名叫str。同时将字符串"hello"(原存放于常数空间)拷贝到这个数组空间中去作为数组的初始化值。 此时若执行return str; 其中的str是数组名。C语言规定,表达式中如果是数组名,则该表达式的值就等于这个数组的地址。所以返回的是这个数组的地址,请注意:并不是字符串常量"hello"的地址!而函数结束时,虽然常数空间并不破坏,但这个数组空间是破坏了的,而你返回的却不是常数空间里的地址而正是已经破坏了的数组的地址。 而char *str="hello"; 是在动态变量区中开辟了一个可以存放一个指针值的变量,名叫str。同时将原存放于常数空间的字符串"hello"的地址赋给这个指针变量作为初始值。 此时若执行return str; 其中的str是指针变量名。C语言规定,表达式中如果是变量名,则该表达式的值就等于这个变量的值。所以返回的是变量str的值,而变量str的值就等于字符串常量"hello"的地址。而函数结束时,变量str破坏了的,但常数空间中的字符串并不破坏。主程序根据返回的地址就可以找到该字符串。 【再补充】 您最后的【问题补充】中的新例子,用了char str[]={'a','b','c'};据我所知,应该是不行的。 您之所以说试验了能行,有两种可能的原因: (1)有可能函数返回后虽然数组str的空间已经被释放了,但暂时该空间还没有被新的内容完全覆盖冲掉,所以您用p[2]访问的时候那个位置里原来的字符还在。 (2)有可能具体某个编译程序对这类数组做了特殊处理(例如强行把它做成了静态的)。按标准,具体的编译程序应该保证符合标准的程序能正确运行,但“不符合标准”的程序并不一定要“不能运行”。如果某个编译程序放宽标准使得某些不合标准的程序也出了正确的结果,这个编译程序不算不标准。 如果是第一种原因,那么程序上下文改一改,就可能不成立了;如果是第二个原因,那么换一个C版本,就可能不成立了。