为什么(和何时)在sizeof之后需要使用括号?


80

以下无法编译:

typedef int arr[10];
int main(void) {
    return sizeof arr;
}

sizeof.c:3: error: expected expression before ‘arr’

但是如果我将其更改为

sizeof(arr);

一切都很好。为什么?


的sizeof当操作员不产品相关图片ANSI-C
严峻

2
@Kostya:我的K&R副本(我拥有的最早的C语言描述)距离很远,我现在无法对其进行检查,但是我有110%的把握确保它所描述的内容sizeof基本上与C99 Standard今天的方式相同。sizeof自1989
。– pmg

Answers:


119

根据6.5.3,有以下两种形式sizeof

sizeof unary-expression
sizeof ( type-name )

由于arr在您的代码中是type-name,因此必须加括号。


15
+1只是为了强调这sizeof是一个运算符:括号“属于”类型,而不是运算符。
2011年

@pmg:感谢您的澄清!是的,正如您提到的,该标准表示sizeof为运营商。
伊势紫藤

4
@pmg:我不知道括号“属于”是什么。第二种形式的语法包括三个标记和一个非终结符:sizeof ( type-name )。但是对于第一种形式,您可以编写例如,sizeof(x)尽管它看起来像一个函数调用(如果sizeof不是关键字),但实际上是应用于括号表达式的运算符。那是你的想法吗?
基思·汤普森

3
我的意思是,sizeof在语法上sizeof <SOMETHING>与函数相对,例如,与printfis相对printf ( <SOMETHING> )。括号属于,printf但不属于sizeof。当sizeof应用到带括号的类型名称时,我想将其视为一无所有-只是“返回”类型。
2011年

2
@pmg:您当然可以这样想,但是我发现它具有误导性。与强制类型转换的唯一真正相似之处在于,它在括号中有一个类型名称,而这只是语法方便的巧合。我更喜欢将sizeof ( type-name )其视为自己的一种表达方式。(标准称它为运算符,但( type-name )按通常的意义而言并不是真正的操作数。)
Keith Thompson

43

这就是指定语言的方式,类型名称必须在此处加括号。

假设语法如下:

sizeof unary-expression sizeof type-name

现在,例如以下表达式将是不明确的:

sizeof int * + 0

可以是sizeof(int *) + 0sizeof(int) * +0。一元表达式不会出现这种歧义,因为附加到表达式的星号不是表达式(但对于某些类型名称,附加一个又是类型名称)。

必须在此处指定一些内容,并要求在类型名称后加上括号,这是解决歧义的一种方法。


-3

我想是因为你有 typedef。如果删除它,则应编译。

来自维基百科的示例:

/* the following code fragment illustrates the use of sizeof     
 * with variables and expressions (no parentheses needed),
 * and with type names (parentheses needed)    
 */
char c;
printf("%zu,%zu\n", sizeof c, sizeof (int));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.