2010-02-05 38 views
12

考虑下面的代码:的sizeof预想不到

#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()的隐式转换?

+3

第二个实际输出'sizeof(int *)',而不是'sizeof(int)'。 'sizeof(int *)'在你的平台上恰好也是4。 – AnT 2010-02-06 03:14:50

+0

另外,假设你的编译器支持那个特定的C99特性,用''%zu''打印'size_t'值('sizeof'返回的值)的正确方法是。如果没有,最好的办法是将其转换为'unsigned'或'unsigned long'。 – 2010-02-06 09:29:38

回答

30

sizeof运算符不评估它的参数,它的操作数只有looks at the type

比方说,你有一个数组a与类型为“T型数组[N]”。然后,在大多数情况下,名称a的类型是“指向T的指针”(T *),并且指针的值是该数组的第一个元素的地址(&a[0])。也就是说,数组的名称“衰减”为指向其第一个元素的指针。在“腐烂”在下列情况下不会发生:

  • a用于与地址的(&)运营商,在a初始化
  • (它是非法分配到阵列中C)和
  • asizeof运算符的操作数。

所以,sizeof a给你Nsizeof(T)

当你做sizeof(a-3)时,sizeof的操作数类型由表达式a-3决定。由于aa-3用于value context(即,上述三个上下文都不是)中,其类型是“指向int的指针”,并且名称a衰变为指向a[0]的指针。因此,计算a-3是未定义的行为,但由于sizeof未评估其参数,所以a-3仅用于确定操作数的类型,因此代码为OK(请参阅上面的第一个链接以获取更多信息)。

从上面,sizeof(a-3)相当于sizeof(int *),这是您的计算机上的4。

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

printf("%zu\n", sizeof(1, a)); 

也将打印sizeof(int *),因为导致a在值上下文习惯逗号操作符的。

+0

+1比我的清晰得多。 – 2010-02-05 15:39:30

5

(a-3)有类型int*,它会打印您在您的平台上是4的sizeof(int*)

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

+6

要清楚 - 只有当操作数是一个可变长度数组时,sizeof'的结果才不是编译器时间常量。对于其他操作数类型它仍然是一个常数。 – 2010-02-05 16:13:45

1

不可以,在第二种情况下,参数被解释为指针在您的机器上碰巧也有大小等于4的int*指针。

1

sizeof()返回一个类型的大小,所以这个类型是重要的。

它也不应该与%d打印。至少,明确地将其转换为unsigned longunsigned long long并使用适当的格式说明符。在教C时,我让一个学生错误地回答了错误的答案,将size_t%d一起打印出来,正如教科书错误地说的那样。

无论如何,a是一个数组类型。在C中,如果几乎任何对象都使用它们或大声喷嚏,数组类型会衰减为指针类型,因此几乎所有对a都会产生指针类型。正如你发现的那样,增加或减少一个数字将会衰减。 (毕竟,算术中不能使用数组,但指针可以使用。)

+0

@David:只要结果不会溢出,如果将表达式转换为'(int)',然后用'“%d”'打印出来就没问题。在这种情况下,几乎可以确定大小将适合'int'。在C99中,当然会使用“%zu”。对于C89,在投射为“(int)”后,你的建议比使用'“%d”'打印更好,因为它更容易出现溢出。 – 2010-02-05 15:42:14

+0

@Alok:没错,但是做这个演员比你投入的要重要得多。另外,我对C89非常熟悉,并没有使用C99,它可能会显示。 – 2010-02-05 17:26:07

+0

OP在他的问题中有演员。我同意你 - 没有演员,'“%d”'是错误的,但只要没有溢出,OP的'printf()'调用就可以。 – 2010-02-05 17:29:04

相关问题