sizeof数组澄清

时间:2011-05-09 06:21:12

标签: c

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

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

如果有功能:

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可能有多大的线索。

6 个答案:

答案 0 :(得分:8)

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

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

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

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

但始终不会应用此隐含转换规则。例如,您发现sizeof运算符适用于数组,甚至&(地址)运算符也适用于原始数组(即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 */

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

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

答案 1 :(得分:2)

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

int
foo (int zap[])

完全等同于

int
foo (int *zap)

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

答案 2 :(得分:2)

zip6 * sizeof(int)的内存块,因此它的大小为24(在您的架构上)。 zap(它也可以在函数声明中写成int *zap)但是可以指向任何内存地址,编译器无法知道从这个(或者甚至包含这个)地址开始有多少空间已被分配。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:-1)

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