为什么函数必须返回 char * 而不是 char 数组?

3
char * printstring(void)
{
    return "my string";
}

既然这个函数返回的是一个字符数组,那么我为什么要在声明中指定我的函数返回char*而不是char[]呢?


4
一个 C 函数无法返回一个数组,但可以返回一个包含数组的结构体。 - Weather Vane
4
无论如何,这个函数应该返回 const char* - Rabbid76
2
@Rabbid76:如果你的意思是“它将有助于检测非法写入访问”,那么你是正确的。但不幸的是,由于传统原因,在C语言中并不需要这样做,这些原因应该在20年前就被深深地埋葬了。 - too honest for this site
1
你需要返回数组的起始地址才能访问数组,可以使用*来获取。我认为我们不能直接返回数组。 - Biswajit Roy
1
“由于该函数返回的是字符数组”,不,实际上并不是!它返回的是数组的地址(在此为字符串),即第一个元素的地址(在此为char)。 - alk
显示剩余7条评论
5个回答

7

由于C语言的设计方式,数组在其中并不是一等公民。你既不能通过值传递将它们传递给函数,也不能返回它们。

如果你想要实现这些功能中的任何一个,你需要将数组包装在一个结构体中。

struct ten_chars{ char chars[10]; };

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

我还没有涉及到结构体,但是为了以后参考你的答案,你是在说有另一种方法可以实现我想做的事情吗? - BareWithImANoob
@BareWithImANoob 是的,我添加了代码。不过这可能是个坏主意。总的来说,在我看来,返回大对象都是不好的。 - Petr Skocik
2
main 函数中,你可以使用 printf("%s\n", printstring().chars); 进行输出。但这是一种不太美观的方式。 - Weather Vane

2
字符串字面量"my string"确实具有数组类型。请注意,sizeof "my string"将计算为10,这是一个包含10个char(包括'\0')的数组的预期大小。您可以将"my string"视为标识符,用于标识数组,并在大多数表达式中衰减为指向数组第一个元素的指针(但不在sizeof表达式中)。
因此,在返回语句中,"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

谢谢您澄清了“my string”会衰减为指针,因为我没有考虑到这一点。 - BareWithImANoob
@BareWithImANoob-- 当然可以...这似乎是回答问题“为什么函数必须返回char *而不是char数组”的答案。 - ad absurdum

2
首先,C语言不允许定义返回数组类型的函数;例如:
char printstring(void)[10] { return "my string"; }

首先,简单地说是不允许的,编译器会因此而报错。

其次,因为你返回的不是一个数组。

除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中的另一个数组的字符串字面值,类型为"N元素T数组"的表达式将被转换("衰变")为类型为"T指针"的表达式,表达式的值将是数组的第一个元素的地址。

表达式"my string"的类型是"10元素char数组"。由于它既不是sizeof或一元&运算符的操作数,也没有用于初始化声明中的char数组,因此它会"衰变"为类型为char *的表达式。它的值是字符串中第一个字符的地址,这个地址值才是你的函数实际返回的值。

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


0
在 C 语言中,不允许将值赋给数组变量。
char a[] = "test";
char b[5] = a; /* ILLEGAL */

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


-2
免责声明:这并不是对问题的确切回答,因为它涉及到而不是。但我认为在这个讨论的背景下可能会很有趣。
在中,有一种返回数组引用的方法,可能看起来像下面这样:
static const char (&func())[12]  {
    return "hello world";
}

这类似于返回指针并且不复制值。但在纯c中是不可能的


1
我已经阅读了您的免责声明。声称不相关并不能使其免责。 - Caleth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接