下面给出的代码段编译,运行时给出结果:
$ make
gcc -g -Wall -o test test.c
$ ./test
string
/ * code1 * /
#include<stdio.h>
char *somefunc1()
{
char *temp="string";
return temp;
}
int main(int argc,char *argv[])
{
puts(somefunc1());
return 0;
}
虽然对此代码略有修改会产生不同的结果:
$ make
gcc -g -Wall -o test test.c
test.c: In function ‘somefunc1’:
test.c:5: warning: function returns address of local variable
$ ./test
/* code 2 */
#include<stdio.h>
char *somefunc1()
{
char temp[] ="string";
return temp;
}
int main(int argc,char *argv[])
{
puts(somefunc1());
return 0;
}
为什么会这样?
答案 0 :(得分:4)
在第一个示例中,您将返回字符串文字的地址。只要程序执行,该文字就存在,因此代码是安全的。
在第二个示例中,您将创建一个(函数本地)数组,该数组初始化为包含字符串string
。然后继续返回此数组的(第一个元素)的地址,但是一旦离开函数,数组就会被销毁。这是您的编译器警告您的内容。
使用从somefunc1
返回的指针会导致未定义的行为,因为它不再引用现有对象。
答案 1 :(得分:4)
char *temp = "string";
将创建指向字符串litteral的指针temp
。该字符串文字存储在可执行代码的数据段中。它是不可变的,并且在函数返回后地址仍然有效。
char temp[] = "string";
将在堆栈上分配7个字符,并将它们设置为“string”。这些是可变的字符。在您的示例中,返回的值指向在函数返回时不再有效的字符。
答案 2 :(得分:1)
退出函数后堆栈变量会丢失,因此在第二种情况下会出现“奇怪行为”。
答案 3 :(得分:-1)
当你做char * temp =“string”时; temp的内存在堆中分配并保持在那里直到执行程序。而当你做char temp [] =“string”; 内存在堆栈上分配,一旦超出范围,就会被删除或无效。在第二种情况下的程序中,一旦你在函数something1之外,返回的指针就变得无效。在第一种情况下,因为数组在堆上,所以内存不会失效。但后来你成功泄露了记忆。