【问题标题】:Why does the function have to return a char * but not a char array?为什么函数必须返回 char * 而不是 char 数组?
【发布时间】:2017-07-26 19:15:18
【问题描述】:
char * printstring(void)
{
    return "my string";
}

既然函数的作用是返回一个字符数组,为什么我必须在声明时声明我的函数返回 char* 而不是 char[]

【问题讨论】:

  • C 函数不能返回数组,尽管它可能返回包含数组的struct
  • 这个函数无论如何都应该返回const char*
  • @Rabbid76:如果您的意思是“这将有助于检测非法写入访问”,那么您是正确的。但不幸的是,由于遗留原因,它在 C 中不需要,这些原因本应深埋 20 年。
  • 您需要返回数组的起始地址才能访问您可以使用 *.我不认为我们可以直接返回数组。
  • "因为函数所做的是返回一个字符数组" 不,完全不是!它返回数组的地址(此处为字符串)第一个元素(此处为 char)。

标签: c arrays string pointers


【解决方案1】:

由于 C 的设计方式,数组不是其中的一等公民。您既不能返回它们,也不能按值将它们传递给函数。

如果你想实现其中任何一个,你必须将数组包装在一个结构中。

struct ten_chars{ char chars[10]; };

struct ten_chars printstring(void)
{
    return (struct ten_chars){"my string"};
}

【讨论】:

  • 我还没有到结构,但只是为了稍后参考您的答案,您是说还有另一种方法可以实现我想要做的事情吗?
  • @BareWithImANoob 是的。我添加了代码。不过,这可能是个坏主意。在我看来,一般来说,返回大对象是。
  • main 你可以有printf("%s\n", printstring().chars); 但这是一种丑陋的做法。
【解决方案2】:

字符串文字"my string" 确实具有数组类型。请注意,sizeof "my string" 的计算结果为 10,这与包含 10 个 chars(包括 '\0')的数组的预期一致。您可以将"my string" 视为标识数组的标识符,并在大多数表达式中衰减为指向数组第一个元素的指针(但不是在例如sizeof 表达式中)。

因此,在 return 语句中,"my string" 衰减为指向数组的第一个元素的指针,该数组包含字符串文字(和空终止符)的字符。函数返回的正是这个指针,这就是为什么返回类型必须是char *

为了记录,C 中的函数甚至不可能返回一个数组,尽管你可以返回一个指向数组的指针。您还可以返回包含来自函数的数组字段的 struct

看看这个示例代码:

#include <stdio.h>

char * getstring(void);

int main(void)
{
    printf("%s\n", getstring());

    return 0;
}

char * getstring(void)
{
    printf("sizeof \"my string\": %zu\n", sizeof "my string");
    printf("*(\"my string\" + 1): %c\n", *("my string" + 1));

    return "my string";
}

程序输出:

sizeof "my string": 10
*("my string" + 1): y
my string

【讨论】:

  • 感谢您澄清“我的字符串”会衰减为指针,因为我没有考虑到这一点
  • @BareWithImANoob--当然......这似乎是问题的答案,“为什么函数必须返回 char * 而不是 char 数组?”
【解决方案3】:

首先,C 不允许您定义返回数组类型的函数。像

char printstring(void)[10] { return "my string"; }

根本不允许,编译器会因为它对你大喊大叫。

其次,因为您返回的不是数组。

除非它是sizeof 或一元&amp; 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则类型为“T 的 N 元素数组”的表达式将被转换(“decay”)为“pointer to T”类型的表达式,表达式的值将是数组第一个元素的地址。

表达式 "my string" 的类型为“char 的 10 元素数组”。由于它不是sizeof 或一元&amp; 运算符的操作数,并且由于它不用于在声明中初始化char 数组,因此它“衰减”为@ 类型的表达式987654331@。它的值是字符串中第一个字符的地址,该地址值是您的函数实际返回的值。

这是设计使然——这是 Ritchie 在 C 中保留 B 的数组语义的一种方式。然而,这意味着 C 中的数组表达式在大多数情况下不保留它们的数组特性。

【讨论】:

    【解决方案4】:

    在 C 中,不允许分配给数组变量。

    char a[] = "test";
    char b[5] = a; /* ILLEGAL */
    

    那么为什么要定义一个返回数组的函数,如果它的结果​​可以分配给任何东西呢?

    【讨论】:

      【解决方案5】:

      免责声明:这不是问题的确切答案,因为它是关于c++,而不是c。但我认为在这个讨论的背景下可能会很有趣。

      c++ 中有一种方法可以返回对数组的引用,如下所示:

      static const char (&func())[12]  {
          return "hello world";
      }
      

      这类似于返回一个指针并且不复制值。但在普通的c不可能

      【讨论】:

      • 我阅读了您的免责声明。否认无关紧要并不能免除它
      猜你喜欢
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-03
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      • 2013-11-14
      相关资源
      最近更新 更多