为什么C函数不能返回数组类型?

时间:2015-09-17 00:49:01

标签: c arrays return return-type

我是C语言的新手,我想知道:

为什么C函数不能返回数组类型?

我知道数组名是数组第一个值的地址,数组是C中的二等公民。

4 个答案:

答案 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年内没有改变它。