为什么不能在C中将数组作为函数参数传递?


12

此评论,我试图谷歌为什么,但我的谷歌福失败。

来自链接的评论:

[...]但重要的是,数组和指针在C中是不同的东西。

假设您没有使用任何编译器扩展,通常就不能将数组本身传递给函数,但是可以传递指针,并像建立数组一样对指针进行索引。

您实际上在抱怨指针没有附加长度。您应该抱怨数组不能作为函数参数传递,或者数组隐式降级为指针。


我不确定是不是答案,但是数组类型的一部分是它的大小,因此我相信您必须为每个要接受的大小定义一个函数。
clcto

您是指函数指针吗? 请澄清问题。
user949300 2014年

2
@ user949300不,从评论的上下文来看很清楚;您不能将数组传递给函数,因为它变成了指针,并且他想知道为什么会这样。
2014年

@DocBrown rlemon建议对此进行编辑。
Florian Margaine 2014年

Answers:


18

我的第一个猜测仅仅是出于性能和内存节省的原因,也是为了简化编译器的实现(尤其是对于C语言诞生时的那种计算机)。“按值”传递巨大的数组似乎会对堆栈产生巨大的影响,它需要对每个函数调用进行完整的数组复制操作,并且可能编译器必须更聪明才能输出正确的汇编代码(尽管最后一点值得商)) 。从语言语法的角度来看,将动态分配的数组与静态分配的数组一样对待也将更加困难。

编辑:从该链接中读取了一些部分后,我认为真正的原因(以及结构中的数组被视为值类型,而唯一数组未被视为原因的原因)是对C的前身B向后兼容性。这是Dennis Ritchie的引用:

该解决方案构成了无类型BCPL和类型C之间的演化链中的关键跳跃。它消除了指针在存储中的实现,而当在表达式中提及数组名称时导致了指针的创建。在今天的C语言中仍然存在的规则是,当数组类型的值出现在表达式中时,会将它们转换为指向组成数组的第一个对象的指针。

尽管语言的语义发生了根本性的变化,但本发明使大多数现有的B代码能够继续工作。[..]


5
一个struct Foo { int array[N]; } 可以按值传递。最后,关于处理动态和静态分配的最后一点似乎也很糟糕(从严格意义上说,数组始终包含大小,数组索引之类的统一概念是指针与数组到指针的衰变相结合),您能详细说明一下吗?

@delnan:我认为这里所述的一般原则是合理的。显然,如果将数组包装在结构中,则需要指定意图。在一般情况下,您几乎总是会参考引用。
罗伯特·哈维

我还发现OP中不必要地引用了该评论,因此过于腐。显然,您要传递一个指针,而不是按值传递数组。但是,同样有效的是,您正在通过引用有效地传递数组。如果反对意见是没有长度限制,那么通过它也很容易。
罗伯特·哈维

@RobertHarvey在类型系统中,这仍然是不对称的:除了数组类型之外,其他所有东西都是通过值传递的(即使属于结构类型的数组通过值传递的),甚至使用完全相同的符号(都在调用位置)并在功能签名中)。

@delnan:除了您必须记住之外,为什么这与之相关?
罗伯特·哈维

9

一台只有8 kB内存的PDP微型计算机无法分配很大的堆栈。因此,在这样的机器上,必须在语言设计(或演化)上保持谨慎,以便能够将期望的通用子例程调用用法所需的堆栈最小化。如今,C仍用于对内存受限(几kB)的嵌入式系统进行编程,因此通常要权衡利弊。

在具有很少寄存器的处理器体系结构上,通过指针而不是通过值传递任何数组的频率更高,这允许将寄存器用作子例程调用优化。


2
我有一些带有256字节RAM的数据板和2K EEPROM的代码板。您不想在那里复制数组。
杰里·耶利米
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.