sizeof数组澄清

我正在C中学习明天的最后一个,并对sizeof运算符有疑问。

假设int的大小是32位,指针是64位。

如果有function:

 int foo (int zap[]) { int a = sizeof(zap); return a; } 

因为zap是一个指针,所以foo会返回8 ,因为存储这个特定指针需要多少字节。 但是,使用以下代码:

 int zip[] = { 0, 1, 2, 3, 4, 5 }; int i = sizeof(zip); 

i将是6 * sizeof(int) = 6 * 4 = 24

为什么sizeof(zip)返回的元素数量乘以每个元素的大小,而sizeof(zap)返回指针的大小? zap的大小是未指定的, zip不是吗? 编译器知道 zip6元素,但是没有关于zap可能有多大的线索。

这在C语法中是不对称的。 在C中,不可能将数组传递给函数,因此当您在其中一个参数的函数声明中使用数组语法时,编译器会将其作为指针读取。

在大多数情况下,当您在表达式中使用数组时,数组会隐式转换为指向其第一个元素的指针,这正是您调用函数时所发生的情况。 在以下代码中:

 int bar[] = {1,2,3,4}; foo(bar); 

数组被转换为指向第一个元素的指针,这就是函数接收的内容。

然而,这种隐含转换规则并不总是适用。 正如您发现的那样, sizeof运算符在数组上工作,甚至& (address-of)运算符也适用于原始数组(即sizeof(*&bar) == 4*sizeof(int) )。

C中的函数不能将数组作为参数接收,它只能接收指向第一个元素的指针,或者指向数组的指针……或者必须将数组包装在结构中。

即使你在函数声明中的括号之间放了一个数字……

 void foo(int x[4]) { ... } 

编号完全忽略了这个数字……编译器的声明完全等同于

 void foo(int *x) { ... } 

例如,即使调用它传递一个不同大小的数组也不会触发任何错误……

 int tooshort[] = {1,2,3}; foo(tooshort); /* Legal, even if probably wrong */ 

(实际上编译器可以发出警告,但代码完全合法C,如果编译器遵循标准则必须接受)

如果你认为这个关于数组的规则在函数参数中是奇怪的那么我同意,但这就是C语言的定义方式。

因为zip是一个数组 ,编译器在编译时知道它的大小。 它只是对两个不同的东西使用相同的符号的情况,这在C中很常见。

 int foo (int zap[]) 

完全等同于

 int foo (int *zap) 

编译器不知道zap有多大(所以它留给了程序员找到的任务)。

zip是一个6 * sizeof(int)的内存块,所以它的大小为24(在你的架构上)。 zap (它也可以在函数声明中写成int *zap )但是可以指向任何内存地址,并且编译器无法知道从这个(甚至包含这个)地址开始分配了多少空间。

zip的大小在编译时是已知的,而zap的大小则不是。 这就是为什么你得到sizeof(zap)上的指针sizeof(zap)sizeof(zip)上数组的大小。

在某些情况下,arrays会衰减到指针。 函数调用就是其中之一。

因为它已经被6个elemens静态初始化。