继此评论,我试图谷歌为什么,但我的谷歌福失败。
来自链接的评论:
[...]但重要的是,数组和指针在C中是不同的东西。
假设您没有使用任何编译器扩展,通常就不能将数组本身传递给函数,但是可以传递指针,并像建立数组一样对指针进行索引。
您实际上在抱怨指针没有附加长度。您应该抱怨数组不能作为函数参数传递,或者数组隐式降级为指针。
继此评论,我试图谷歌为什么,但我的谷歌福失败。
来自链接的评论:
[...]但重要的是,数组和指针在C中是不同的东西。
假设您没有使用任何编译器扩展,通常就不能将数组本身传递给函数,但是可以传递指针,并像建立数组一样对指针进行索引。
您实际上在抱怨指针没有附加长度。您应该抱怨数组不能作为函数参数传递,或者数组隐式降级为指针。
Answers:
我的第一个猜测仅仅是出于性能和内存节省的原因,也是为了简化编译器的实现(尤其是对于C语言诞生时的那种计算机)。“按值”传递巨大的数组似乎会对堆栈产生巨大的影响,它需要对每个函数调用进行完整的数组复制操作,并且可能编译器必须更聪明才能输出正确的汇编代码(尽管最后一点值得商)) 。从语言语法的角度来看,将动态分配的数组与静态分配的数组一样对待也将更加困难。
编辑:从该链接中读取了一些部分后,我认为真正的原因(以及结构中的数组被视为值类型,而唯一数组未被视为原因的原因)是对C的前身B的向后兼容性。这是Dennis Ritchie的引用:
该解决方案构成了无类型BCPL和类型C之间的演化链中的关键跳跃。它消除了指针在存储中的实现,而当在表达式中提及数组名称时导致了指针的创建。在今天的C语言中仍然存在的规则是,当数组类型的值出现在表达式中时,会将它们转换为指向组成数组的第一个对象的指针。
尽管语言的语义发生了根本性的变化,但本发明使大多数现有的B代码能够继续工作。[..]
struct Foo { int array[N]; }
可以按值传递。最后,关于处理动态和静态分配的最后一点似乎也很糟糕(从严格意义上说,数组始终包含大小,数组索引之类的统一概念是指针与数组到指针的衰变相结合),您能详细说明一下吗?