C:为什么可以按值传递(给函数)结构,而不是数组?
C: Why can you pass (to a function) a struct by value, but not an array?
背后有什么历史或逻辑原因吗?
说明:
当你将数组传递给 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 function(int array[10])
和 int function(int *array)
相同,因为 6.7.5.3 函数声明符(包括原型)(http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf 第 118 页)
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if
any) are those specified within the [ and ] of the array type
derivation. If the keyword static also appears within the [ and
] of the array type derivation, then for each call to the
function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as many
elements as specified by the size expression
.
结构用于声明自己的数据类型,具有原始数据类型,如 int、float、long(或结构的结构)等。它们应该包含其中的一些,例如学生的结构将包含 id、name、rollno、subjects 等。所以大多数情况下,任何结构元素最多包含 10-20 个字段(在逻辑情况下),因此当您将结构传递给函数时,它必须复制大约 40-100 个字节。复制该结构变量。其中数组可以很大并且用于存储相同类型的信息。如果是整数,它们的大小可以是 10^7,所以如果我们实现一种语言来复制整个数组以进行函数调用,它可能必须复制 (10^7)*4 个字节,这是一个巨大的数量并且会影响性能 badly.and 数组的典型大小是 10^4 到 10^6,这仍然很多。但是,如果您创建 int 数组结构(或任何其他数组),则可以将其作为该数组的副本传递给函数。例如
#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;
}
大多数情况下都不会这样做,但很少有您需要传递数组但又不想更改它们的内容但又需要对其副本进行某种更改并希望 return 复制你可以使用这种数组结构和 return 它们来自 return 类型结构的函数,例如
arrayStruct returnChange(arrayStruct a){
a.arr[2]=332;
return a;
}
在最初的 K&R 中,您不能按值传递结构。那是语法错误。由于许多编译器供应商将其作为扩展提供,因此 pass-by-value 最终进入了标准。
为什么限制,为什么进化?开发 C 语言的机器很小。 64 KB 的段大小很常见。内存很宝贵,既然可以传递地址,为什么还要复制一些东西呢?在堆栈上复制一个 64 字节的结构 是 一个错误,甚至可能不是用户想要的。
到 90 年代中期,情况已不再如此。 32 位寻址和 4 MB 或更大的 RAM 很常见。该限制是一种障碍并导致了一些复杂性,因为如果没有 const
,通过引用传递的结构可能会在不知不觉中被修改。
为什么不对数组做同样的事情?没有需求。如您所知,数组和指针在 C 中密切相关。 C 标准库严重依赖引用传递,考虑 memset
和 strcpy
。按值传递结构意味着只需在调用中删除 &
,而按值传递数组则需要添加新语法。一个编译器供应商提供,比方说,by value
作为 C 语法,会被会议嘲笑。
当然,您可以按值传递数组;您需要做的就是将其包装在 struct
中。但这仅在数组具有确定(且非可变)大小的情况下才有效。您可以在结构中包含无限大小的数组,但生成的类型不完整,只能用作指针的目标。
这可能与我们要得到的解释一样接近。绝大多数作为参数传递的数组都不是固定大小的,即使按值传递它们也是不可能的,这也是不太可能的。
函数有相似(但不同)的衰减;函数不能作为参数传递,只能作为函数指针传递。因为每次你想引用一个函数时显式地写 &
会很乏味,语言会为你处理它。
总的来说,"Why is this language like this snd not like that?"形式的问题只能回答"because that's how it is"。
背后有什么历史或逻辑原因吗?
说明: 当你将数组传递给 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 function(int array[10])
和 int function(int *array)
相同,因为 6.7.5.3 函数声明符(包括原型)(http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf 第 118 页)
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression
.
结构用于声明自己的数据类型,具有原始数据类型,如 int、float、long(或结构的结构)等。它们应该包含其中的一些,例如学生的结构将包含 id、name、rollno、subjects 等。所以大多数情况下,任何结构元素最多包含 10-20 个字段(在逻辑情况下),因此当您将结构传递给函数时,它必须复制大约 40-100 个字节。复制该结构变量。其中数组可以很大并且用于存储相同类型的信息。如果是整数,它们的大小可以是 10^7,所以如果我们实现一种语言来复制整个数组以进行函数调用,它可能必须复制 (10^7)*4 个字节,这是一个巨大的数量并且会影响性能 badly.and 数组的典型大小是 10^4 到 10^6,这仍然很多。但是,如果您创建 int 数组结构(或任何其他数组),则可以将其作为该数组的副本传递给函数。例如
#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;
}
大多数情况下都不会这样做,但很少有您需要传递数组但又不想更改它们的内容但又需要对其副本进行某种更改并希望 return 复制你可以使用这种数组结构和 return 它们来自 return 类型结构的函数,例如
arrayStruct returnChange(arrayStruct a){
a.arr[2]=332;
return a;
}
在最初的 K&R 中,您不能按值传递结构。那是语法错误。由于许多编译器供应商将其作为扩展提供,因此 pass-by-value 最终进入了标准。
为什么限制,为什么进化?开发 C 语言的机器很小。 64 KB 的段大小很常见。内存很宝贵,既然可以传递地址,为什么还要复制一些东西呢?在堆栈上复制一个 64 字节的结构 是 一个错误,甚至可能不是用户想要的。
到 90 年代中期,情况已不再如此。 32 位寻址和 4 MB 或更大的 RAM 很常见。该限制是一种障碍并导致了一些复杂性,因为如果没有 const
,通过引用传递的结构可能会在不知不觉中被修改。
为什么不对数组做同样的事情?没有需求。如您所知,数组和指针在 C 中密切相关。 C 标准库严重依赖引用传递,考虑 memset
和 strcpy
。按值传递结构意味着只需在调用中删除 &
,而按值传递数组则需要添加新语法。一个编译器供应商提供,比方说,by value
作为 C 语法,会被会议嘲笑。
当然,您可以按值传递数组;您需要做的就是将其包装在 struct
中。但这仅在数组具有确定(且非可变)大小的情况下才有效。您可以在结构中包含无限大小的数组,但生成的类型不完整,只能用作指针的目标。
这可能与我们要得到的解释一样接近。绝大多数作为参数传递的数组都不是固定大小的,即使按值传递它们也是不可能的,这也是不太可能的。
函数有相似(但不同)的衰减;函数不能作为参数传递,只能作为函数指针传递。因为每次你想引用一个函数时显式地写 &
会很乏味,语言会为你处理它。
总的来说,"Why is this language like this snd not like that?"形式的问题只能回答"because that's how it is"。