sizeof表现出乎意料

时间:2010-02-05 14:14:14

标签: c

请考虑以下代码:

  #include <stdio.h>
  int main(void)
  {
    int a[10];
    printf("%d",(int)sizeof(a)); //prints 10*sizeof(int) (40 on my compiler)
    printf("%d",(int)sizeof(a-3)); //prints sizeof(int) (4 on my compiler)

  }

我知道sizeof()是一个编译时运算符,但我很惊讶地看到第二个printf()的输出。可能是什么原因?是否将sizeof()的参数从数组类型隐式转换为整数类型?

4 个答案:

答案 0 :(得分:30)

sizeof运算符不会计算其参数,只会计算其操作数的looks at the type

假设你有一个类型为“array [N]类型为T”的数组a。然后,在大多数情况下,名称a的类型是“指向T的指针”(T *),指针的值是数组的第一个元素的地址({{1 }})。也就是说,数组的名称“衰减”到指向其第一个元素的指针。在以下情况下不会发生“腐朽”:

  • &a[0]与地址(a)运算符一起使用时,
  • &的初始化中(在C中分配给数组是非法的)和
  • aa运算符的操作数时。

因此,sizeof为您提供sizeof aN

执行sizeof(T)时,sizeof(a-3)的操作数类型由表达式sizeof决定。由于a-3中的a用于value context(即上述三个上下文中没有一个),因此其类型为“指向int的指针”,名称a-3会衰减指向a的指针。因此,计算a[0]是未定义的行为,但由于a-3不评估其参数,sizeof仅用于确定操作数的类型,因此代码正常(请参阅上面的第一个链接更多)。

从上面可以看出,a-3相当于sizeof(a-3),在您的计算机上为4。

“转换”是由减法运算符引起的。您可以使用逗号运算符查看类似的,也许更令人惊讶的结果:

sizeof(int *)

也会打印printf("%zu\n", sizeof(1, a)); ,因为逗号运算符导致sizeof(int *)在值上下文中使用。

答案 1 :(得分:5)

(a-3)的类型为int*,它会在您的平台上打印出sizeof(int*),即4。

请注意,sizeof()不再是C99中的编译时常量(由于可变长度数组)。

答案 2 :(得分:1)

不,在第二种情况下,参数被解释为int*指针,在您的机器上也恰好等于4。

答案 3 :(得分:1)

sizeof()返回类型的大小,因此类型是重要的。

也不应该使用%d打印。至少,明确地将其强制转换为unsigned longunsigned long long并使用适当的格式说明符。在教授C时,我有一个学生错误地回答size_t%d,因为教科书错误地说了。

无论如何,a是一种数组类型。在C语言中,如果你几乎用它们做任何事情或大声打喷嚏,数组类型就会衰减为指针类型,所以你对a所做的几乎所有操作都会产生指针类型。正如您所知,添加或减去数字会衰减。 (毕竟,数组不能用于算术,但指针可以。)