我是C语言的新手,我想知道:
为什么C函数不能返回数组类型?
我知道数组名是数组第一个值的地址,数组是C中的二等公民。
答案 0 :(得分:6)
你已经自己回答了这个问题:阵列是二等公民。
C按值返回。数组不能通过值传递,因此无法返回它们。
至于为什么数组不能通过值传递:这是K& R在他们第一次设计语言时做出的设计决定,现在改变它已经太晚了,因为所有现有的C代码都会中断。
答案 1 :(得分:5)
基于The Development of the C Language,看起来真正的原因主要与B和BCPL的C演变有关。 B没有数组变量,它只有指针。它也没有结构。当结构被添加到C,并且它们被允许包含数组成员时,他需要一种方法来处理这些封闭的数组,类似于处理B样式数组的方式,并且解决方案是让数组在它们&#时转换为指针。 39;重新用于表达式。以下是本文解释此内容的部分。
当我尝试扩展类型符号时问题变得明显,尤其是 添加结构化(记录)类型。看起来,结构应该以直观的方式映射到记忆中 在机器中,但在包含数组的结构中,没有用于存放指针的好地方 包含数组的基数,也没有任何方便的方式来安排它被初始化。对于 例如,早期Unix系统的目录条目可能在C中描述为
struct { int inumber; char name[14]; };
我希望结构不仅可以表征抽象对象,还可以描述集合 可能从目录中读取的位数。编译器可以在哪里隐藏指针 语义要求的名称?即使结构被认为更抽象,而且 可能会以某种方式隐藏指针空间,我怎样才能正确处理技术问题 在分配复杂对象时初始化这些指针,可能是指定的对象 包含包含任意深度结构的数组的结构?
该解决方案构成了无类型BCPL之间演化链中的关键跳跃 并且键入C.它消除了存储中指针的具体化,而是导致了 在表达式中提到数组名称时创建指针。幸存的规则 在今天的C中,当数组类型的值出现在表达式中时,它们会被转换 指向构成数组的第一个对象的指针。
这不是特定于将数组传递给函数和从函数传递数组,它适用于表达式中使用数组的任何时候(除非它是&
运算符的参数)。 / p>
另请注意,此设计允许在传递给函数时对与malloc()
动态分配的数组变量和内存进行等效处理。
答案 2 :(得分:1)
无法从函数返回数组的原因是数组类型可能不是赋值的目标。你不能写像
这样的东西int arr[N];
arr = foo();
当数组表达式出现在大多数情况下时,它们会失去“数组”。这是Ritchie在C开发早期做出的设计决策的结果。 C来自早期的编程语言B(go figure),后者又来自BCPL。在B中,数组对象是指向数组第一个元素的指针,并且数组访问是根据指针算法定义的。 a[i]
被定义为来自*(a + i);
中存储的地址的i
- 偏移a
元素,并取消引用结果。
Ritchie保留了B的数组语义,但不想将那些语义所需的指针存储放在一边。所以他提出了在大多数情况下数组表达式将被转换(“衰减”)到指针表达式的规则。
这意味着如果arr = foo();
是一个数组类型,arr
就无法工作,因为没有为名为arr
的对象预留存储空间与数组元素本身分开;没有什么可以将分配给。
答案 3 :(得分:0)
因为实际上没有任何类似C的数组类型。
如果愿意,可以返回指向数组的指针。或者你也可以返回一个结构。所以你可以做类似以下的事情。
typedef struct {
things *array;
int iCount;
} MyArrayType;
然后你可以做一些事情,比如分配一个数组,然后返回它。
MyArrayType myFuncIntArray (int iCount)
{
MyArrayType ret = {0};
ret.array = malloc (iCount * sizeof(things));
ret.iCount = iCount;
return ret;
}
当然,您可以更改函数以创建您想要创建的任何类型的数组。完成后,你将负责释放内存。
C是这样做的,因为设计它的聪明人就是这样做的,C标准委员会在40年内没有改变它。