C:为什么你可以按值传递结构,而不是数组?

C:为什么你可以按值传递结构,而不是数组?,c,arrays,struct,pass-by-value,C,Arrays,Struct,Pass By Value,背后有什么历史或逻辑原因 说明: 在C中,当您将数组传递给函数时,实际上只传递指向数组的指针。 但是,当传递结构时,可以传递结构的副本或指针 //this: int function(int array[10]) // is equivalent to this: int function(int *array) //and they both pass a pointer //but this: int function(struct tag name) //passes a struct

背后有什么历史或逻辑原因


说明: 在C中,当您将数组传递给函数时,实际上只传递指向数组的指针。 但是,当传递结构时,可以传递结构的副本或指针

//this:
int function(int array[10])
// is equivalent to this:
int function(int *array)
//and they both pass a pointer

//but this:
int function(struct tag name)
//passes a struct by value, where as this:
int function(struct tag *name)
//passes a pointer to it.

为什么不同?

两种函数声明中的类型都不同-

struct tag  /* and */ struct tag *
一个是结构变量,另一个是指向结构的指针

您可以对结构执行类似操作-

int function(struct tag name[])  /*--> int function(struct tag *name)  */
上述内容是等效的。

int函数(int数组[10])
int函数(int*数组)
是相同的,因为6.7.5.3函数声明器(包括原型)(第118页)

7应调整“类型数组”的参数声明 到“类型的限定指针”,其中类型限定符(如果 any)是在数组类型的[and]中指定的 起源如果关键字static也出现在[和]中 ]数组类型派生,然后针对每个调用 函数,则对应的实际参数的值 提供对数组的第一个元素的访问,该元素的数量至少为 由大小表达式指定的元素


.

结构用于声明自己类型的数据类型,原始数据类型包括int、float、long(或structs of structs)等。它们应该包含一些数据类型,例如,学生结构将包含id、name、rollno、subject等。因此,大多数结构元素最多包含10-20个字段(在逻辑情况下),因此,当您将结构传递给函数时,它必须复制大约40-100个字节才能复制该结构变量。其中as阵列可以具有巨大的尺寸,并用于存储相同类型的信息。如果是整数,它们的大小可能是10^7,因此如果我们实现一种语言来复制整个数组以进行函数调用,它可能必须复制(10^7)*4字节,这是一个巨大的量,会严重影响性能。而数组的典型大小是10^4到10^6,这仍然是一个很大的数目。但如果创建int数组(或任何其他数组)的结构,则可以将其作为该数组的副本传递给函数。e、 g

#include<stdio.h>

typedef struct {
    int arr[10];
}arrayStruct;

void change(arrayStruct a){
    a.arr[2]=5;
}
int main(){
    arrayStruct a;
    for(int i=0;i<10;i++){
        a.arr[i]=i;
    }
    printf("Before:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    change(a);
    printf("\nAfter:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    return 0;
}

在原始K&R中,无法按值传递结构。这是一个语法错误。由于许多编译器供应商将其作为扩展提供,传递值最终进入了标准

为什么是限制,为什么是进化?C开发的机器很小。64 KB的段大小是常见的。记忆是珍贵的,既然你可以传递地址,为什么还要复制一些东西呢?在堆栈上复制64字节的结构是一个错误,甚至可能不是用户想要的

到了20世纪90年代中期,这已不再是事实。32位寻址和4MB或更大的RAM是常见的。这种限制是一种阻碍,并导致了一些复杂性,因为如果没有
const
,通过引用传递的结构可能会被修改,可能是无意中修改的

为什么不对数组执行相同的操作?没有需求。正如您所知,数组和指针在C中是密切相关的。C标准库很大程度上依赖于引用传递,考虑<代码> MyStase<代码>和<代码> StrucP。按值传递结构意味着在调用中删除
&
,而按值传递数组则需要添加新语法。比如说,一家编译器供应商提供了C语法的
按值
,可能会在会议上被嘲笑

当然,可以按值传递数组;您只需将其包装在
结构中
。但这仅在数组具有确定(且非可变)大小时才有效。可以在结构中包含无限大小的数组,但生成的类型不完整,只能用作指针的目标

这可能是我们将要得到的解释。绝大多数作为参数传递的数组的大小都不是固定的,按值传递数组是不可能的,即使是有意的,也是不可能的

函数存在类似(但不同)的衰减;函数不能作为参数传递,只能作为函数指针传递。由于每次需要引用函数时显式编写
&
都会很繁琐,因此语言会为您处理好它


总的来说,“为什么这种语言是这样的,而不是那样的?”这种形式的问题只能回答“因为它是这样的”

嗯?“这是如何回答这个问题的?”我想大卫法利。我想OP没有意识到这一点,否则他不会对此感到困惑。在我看来,这个问题似乎是这样的,因为所有的贴花都是不可比较的。@ameyCU“我想”并没有回答“如何?”。Davidefaeli是OP.@ameyCU-我想你不明白这个问题。我在问为什么在C语言中,你可以将结构的副本传递给函数,但你不能传递数组的副本…@ameyCU是的,问题似乎是“为什么?”。你可以按值传递数组,但数组的值是指向它的第一个元素的指针(不是指向数组的指针)。指向结构的指针也是指向它的第一个值的指针,如果我没有弄错的话,不,这些是不同的(例如,类型不匹配)。我认为这个问题的可能重复更多地属于programmers.SE。值得注意的是,K&R C不允许值传递/返回
struct
s。
arrayStruct returnChange(arrayStruct a){
    a.arr[2]=332;
    return a;
}