我开始学习C,我不明白我做错了什么。这是一个函数的简单代码,它返回pid +“。data”。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char * getfilename(){
char name[60];
sprintf(name,"%i.data",getpid());
return name;
}
void main(){
char* name = getfilename();
printf("%s",name);
}
输出:��#�a
。
所以我猜我做错了。
答案 0 :(得分:4)
char * getfilename(){
char name[60];
sprintf(name,"%i.data",getpid());
return name;
}
name
返回后,您无法访问getfilename
个对象。自动对象name
的生命周期在getfilename
最后}
处结束。在函数返回后访问它是未定义的行为。
作为临时修复,您可以将name
指定为static
,它会起作用。但是你应该做的是让getfilename
函数接受一个指针参数来写入文件名。
修改强>
为什么我不建议使用strdup
?
strdup
不是标准C函数。 strdup
生活在POSIX世界。出于便携性的原因,我尽可能使用标准C功能。strdup
执行隐藏的malloc
通话,您不必忘记执行free
。这与标准C库的所有函数相反,后者从不调用malloc
(或实际上从不出现来调用malloc
)。 strdup
是一个糟糕的API设计。strdup
正在执行字符串的副本。为什么需要执行额外的副本?只需将字符串写入可以检索它的位置即可。 答案 1 :(得分:3)
一种解决方案是使用strdup,即更改:
return name;
为:
return strdup(name);
这使用动态内存分配(即malloc)制作临时(本地)字符串的副本。
当然,您必须确保在完成此字符串后随后free。
你需要:
#include <string.h> // strdup()
#include <stdlib.h> // free()
答案 2 :(得分:1)
char name[60]
存在于堆栈中,但只有在getfilename()
之后才被释放,因此任何引用(也由getfilename()
返回)都会变为无效。
答案 3 :(得分:1)
char name[60]
是一个局部变量,在调用函数时分配,并在返回时释放。当你试图返回它时,你真的返回它的地址(在所有数组主要是指针算术的语法糖之后)。现在,您的调用者有一个指向已释放的内存块的指针,因此可能包含垃圾。
答案 4 :(得分:1)
您无法从函数name
返回数组getfilename
,因为它是一个(常规)局部变量,当函数返回时会清除它们。
因此,当您返回main
并尝试打印返回的值时,指针name
指的是已被重用于其他目的的内存块。
这个问题有几种解决方案:
name
getfilename
中设置static
。这将确保它超过对getfilename
的调用并且可以安全返回,但缺点是对getfilename
的所有调用都使用相同的缓冲区。malloc
动态分配数组(完成后,请不要忘记使用free
进行清理)答案 5 :(得分:0)
如其他答案中所述,您无法返回指向函数堆栈中某处的指针。
您只需将分配的数组传递给getfilename()
函数即可。您可以按如下方式重写程序。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void getfilename(char * name)
{
sprintf(name,"%i.data",getpid());
}
int main(void)
{
char name[60];
getfilename(name);
printf("%s\n",name);
return 0;
}
这应该可以正常工作。