sizeof表现出乎意料

Pra*_*rav 12 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)

  }
Run Code Online (Sandbox Code Playgroud)

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

Alo*_*hal 30

sizeof运营商不评价它的参数,它仅着眼于类型的操作数.

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

  • when a与address-of(&)运算符一起使用时,
  • 在初始化中a(在C中分配给数组是非法的),和
  • when a是运算sizeof符的操作数.

所以,sizeof a给你N时间sizeof(T).

执行sizeof(a-3)此操作时,操作数的类型sizeof由表达式确定a-3.由于ain a-3用于值上下文(即上述三个上下文中没有一个),因此其类型为"指向int的指针",并且名称a衰减为指向的指针a[0].因此,计算a-3是未定义的行为,但由于sizeof不评估其参数,a-3仅用于确定操作数的类型,因此代码是正常的(请参阅上面的第一个链接以获取更多信息).

从上面来看,sizeof(a-3)相当于sizeof(int *)你计算机上的4.

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

printf("%zu\n", sizeof(1, a));
Run Code Online (Sandbox Code Playgroud)

也将打印sizeof(int *),因为逗号运算符导致在a值上下文中使用.


Ale*_*tov 5

(a-3)有类型int*,它打印你sizeof(int*)平台上的4.

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

  • 要清楚 - 只有当操作数是一个可变长度数组时,`sizeof`的结果才不是编译器时间常量.对于其他操作数类型,它仍然是常量. (6认同)