返回一个字符串指针

时间:2012-11-12 13:06:24

标签: c linux posix

我开始学习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

所以我猜我做错了。

6 个答案:

答案 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指的是已被重用于其他目的的内存块。

这个问题有几种解决方案:

  1. name getfilename中设置static。这将确保它超过对getfilename的调用并且可以安全返回,但缺点是对getfilename的所有调用都使用相同的缓冲区。
  2. 使用malloc动态分配数组(完成后,请不要忘记使用free进行清理)
  3. 传递缓冲区以将值存储为参数。

答案 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;
}

这应该可以正常工作。