【问题标题】:Returned string value becomes garbage返回的字符串值变成垃圾
【发布时间】:2013-02-07 19:55:43
【问题描述】:

我试图将字符 array 值传递给字符 pointer。然后这个值被返回给调用它的方法,但是在它被返回之后,这个值就变成了垃圾。谁能帮帮我?

#include <stdio.h>

const char * getname(){
     char nam[10];
     char * name;
     gets(nam);
     name = nam;
     return name;
}
main(){
       printf("%s",getname());
       getch();
}

一切都很好,直到字符串被返回

【问题讨论】:

  • 停止返回被调用函数中局部变量的地址。你正在做的是未定义的行为。并使用fgets() 而不是gets()。该功能太糟糕了,在 C11 中被彻底淘汰,在 C99 中已弃用。
  • 我希望这个问题很容易搜索,对于初学者来说很常见。另外,OP,您不需要指针变量。数组在必要时衰减为指向第一个元素的指针,您可能只是(仍然不正确地)编写:return nam;
  • 我们还要记住gets() 是那些没有缓冲区溢出保护的危险函数之一。你最好使用fgets(),比如stackoverflow.com/questions/4023895/…

标签: c string char return


【解决方案1】:

nam 变量具有函数作用域。这意味着一旦函数结束,该变量的内存就会被释放。所以你返回的指向那个内存的指针将不再有效。

你可以传入指针:(在这种情况下有点无意义,如你所见)

void getname(char *name)
{
  gets(name);
}

你可以malloc(不好,因为你需要在某个时候再次free):

const char * getname(){
     char * name = malloc(10);
     gets(name);
     return name;
}

【讨论】:

  • +1 还提到“通常如何解决这个常见问题”设计方面
  • 是的,在 C 语言中,您必须随时查看分配的内容和释放的内容。 C++ 可以为您完成大部分工作,但在 C 中无法逃脱。
  • 您的代码中有小错误,正确的是gets(name);
【解决方案2】:

nam 的范围是函数 getname() 的本地,您通过 name 指针返回 nam 地址

const char * getname(){
     char nam[10];
     :
     name = nam;
     return name;
}

nam; 动态分配内存。喜欢:

nam = malloc(sizeof(char)*10);

另外可能有bufferoverun不要使用gets(),喜欢:

nam = malloc(sizeof(char)*10);
fgets( nam, 10, stdin ); 

你也不需要使用name 一个额外的变量简单的return nam 是好的。

const char * getname(){
     char * nam = malloc(sizeof(char)*10);
     fgets( nam, 10, stdin ); 
     return nam;
}

【讨论】:

  • 不必写sizeof(char),因为它的定义是1。
  • @JanHudec 是的,没有必要:)
  • 同意。额外的sizeof(char) 没有伤害,忘记sizeof(int) 肯定会。
  • @JanHudec 是的,这就是为什么我认为使用sizeof 是一种很好的做法,谢谢!
  • @paxdiablo 感谢您的建议。是的! char *nam = malloc (10 * sizeof(*nam)); 是正确的选择。谢谢。我们不是在“竞争”,而是一起帮助。 :)
【解决方案3】:

您的问题是 return name 正在返回堆栈变量的地址,该地址在函数返回后超出范围。

有几种方法可以解决这个问题(至少)。

首先是在函数分配地址,然后传入:

char *getname (char *buff) {
    strcpy (buff, "pax");
    return buff;
}

char name[20];
printf ("Name is '%s'\n", getname (name));

第二个是使用分配函数,不会在函数退出时超出范围(指针可能,但只要你将它们传回,你仍然可以到达分配的内存):

char *getname (void) {
    char *buff = malloc (21);        // should really check this for failure.
    strcpy (buff, "pax");
    return buff;
}

buff = getname();
printf ("Name is '%s'\n", buff);
free (buff);                         // This is important, caller is responsible
                                     //   for freeing the memory.

【讨论】:

    【解决方案4】:

    声明nam static 也可以:

    const char * getname() {
      static char nam[10];
      ...
    

    注意:此代码不是线程安全的,因为 nam 现在被视为全局声明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      相关资源
      最近更新 更多