为什么你不能在C中返回固定大小/ const数组?

use*_*142 8 c arrays pointers

我想知道为什么不能在C中返回数组?毕竟,数组只是一个由大小信息支持的指针(以便sizeof工作).首先我认为这是为了防止我返回我的堆栈上定义的数组,但没有什么能阻止我将指针返回到我的堆栈上的东西(gcc警告我,但代码编译).而且我也可以返回字符串文字,这是静态存储的字符数组.顺便说一句,在lunux中存储它.rodata,并且const数组也存储在那里(检查它objdump),所以我可以返回数组(将它转换为指针)并且它可以工作,但是AFAIK这只是特定于实现的(另一个操作系统) /编译器可以在堆栈上存储const).

我有2个想法如何实现数组返回:只需将其复制为值(就像它为结构所做的那样.我甚至可以将数据包装到结构中!!),并自动创建指针或允许用户返回const数组和创建这样的数组应具有静态存储持续时间的合同(就像它对字符串所做的那样).这两个想法都是微不足道的!所以,我的问题是为什么K&R没有实现类似的东西?

M.M*_*M.M 13

数组不是"只是一个由大小信息支持的指针".

数组是某种类型的连续元素块.没有指针.

由于数组是一个对象,因此可以形成一个指向数组或指向数组元素之一的指针.但是这样的指针不是数组的一部分,并且不与数组一起存储.说"一个int只是一个由1int 大小支持的指针" 是很有意义的.

编译器已知数组的大小,其方式与已知任何对象的大小相同.如果我们double d;知道那sizeof dsizeof(double)因为编译器会记住这d是一个类型的对象double.

什么都阻止我返回指向我的堆栈上的东西的指针

C标准阻止您执行此操作(并使用返回的指针).如果您编写的代码违反了标准,那么您就是自己的代码.

我也可以返回字符串文字

字符串文字是char数组.在return语句中使用数组时,它将转换为指向第一个元素的指针.

要按值返回(和分配)数组,必须更改有关将数组转换为指针(有时称为"衰减")的规则.这是可能的,但K&R决定在设计C时几乎无处不在.

事实上,有可能拥有像C这样的语言,但根本没有衰变.也许在后见之明可以省去很多困惑.然而,他们只是选择以他们的方式实施C.


在K&R C中,也无法按价值返回结构.任何非原始类型的复制操作都必须使用memcpy或等效的迭代副本完成.考虑到20世纪70年代硬件资源的方式,这似乎是一个合理的设计决策.

ANSI C增加了按值返回结构的可能性,但到那时,即使他们想要改变衰减规则也为时已晚; 它会破坏许多依赖于衰变规则的现有代码.


Dol*_*000 11

从技术上讲,你可以返回一个数组; 你不能"直接"做到这一点,但必须将它包装在一个结构中:

struct foo {
    int array[5];
};

struct foo returns_array(void) {
    return((struct foo) {
        .array = {2, 4, 6, 8, 10}
    });
}
Run Code Online (Sandbox Code Playgroud)

但是为什么C不允许你直接做到这一点,尽管它有能力仍然是一个很好的问题.它可能与它不支持整个数组赋值的事实相关:

void bar(int input[5]) {
    int temp[5];

    temp = input;   <-- Doesn't compile
}
Run Code Online (Sandbox Code Playgroud)

当然,更令人陌生的是,支持通过参数传递的全数组拷贝.如果有人知道如何找到ANSI委员会关于此事的决定,那将会很有趣.

然而,

毕竟,数组只是一个由大小信息支持的指针(使sizeof工作).

这是不正确的.数组没有显式指针,也没有任何存储的大小.数组存储为原始值,打包在一起; 大小只在编译器中已知,并且永远不会在程序中显式为运行时数据.当您尝试将其用作指针时,该数组会衰减为指针.

  • “支持通过参数传递进行整个数组复制”。不,不支持此操作。仅当数组是结构中的字段时。 (2认同)