为什么sizeof int是错误的,而sizeof(int)是正确的呢?


96

我们知道这sizeof是一个用于计算任何数据类型和表达式的大小的运算符,并且当操作数是表达式时,可以省略括号。

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

第一种用法sizeof是错误的,而其他用法是正确的。

使用gcc进行编译时,将显示以下错误消息:

main.c:5:9: error: expected expression before int

我的问题是,为什么C标准不允许这种操作。会sizeof int引起歧义吗?


5
有趣的是,并非所有表达式都没有括号就可以接受:try sizeof (int)a
弗雷德·富

2
@MikkelK .: OP正在询问标准语录背后的推理,他已经知道标记答案中提到的语录。
Alok保存

2
@Lundin:sizeof +(int)a*&实际编译具有优势;-)
Steve Jessop

2
@SteveJessop嗯,不是左值。尽管它确实在Embarcadero C ++中进行了编译,但奇怪的是。无论如何,我相信我们刚刚发现了一元+运算符的用法!那肯定是C编程历史上的第一次:)
Lundin 2012年

2
@Lundin:一元还是要小心+。例如,sizeof +(char)a == sizeof(int)由于整数的提升,如果您完全担心要尝试使用的表达式的大小,只需将括号放在括号中可能不太容易出错。所以我不确定是否会称其为“一种用途”,尽管我承认我确实使用过……
Steve Jessop 2012年

Answers:


101

以下可能是模棱两可的:

sizeof int * + 1

(sizeof (int*)) + 1,还是(sizeof(int)) * (+1)

显然,C语言可能已经引入了解决歧义的规则,但是我可以想象为什么它不会打扰您。就目前的语言而言,类型说明符永远不会在表达式中出现“裸露”状态,因此不需要规则来确定第二个*是类型的一部分还是算术运算符。

现有的语法确实已经解决了的潜在歧义sizeof (int *) + 1。是的(sizeof(int*))+1不是 sizeof((int*)(+1))

C ++有一个类似的问题可以使用函数样式转换语法解决。你可以写int(0),你可以写typedef int *intptr; intptr(0);,但是你不能写int*(0)。在这种情况下,解决方案是“裸”类型必须是一个简单的类型名称,它不能只是任何可能带有空格或尾随标点符号的旧类型ID。我不确定,也许sizeof可以使用相同的限制进行定义。


1
C ++有new int*(X)这将是不明确的,如果C ++ didnt指定新的运营商采取那些可能是一个类型中最长的字符串。因此,我想在C ++中,它们可以使用sizeof进行相同的处理。但是在C ++中,您可以说出sizeof int()哪一个是模棱两可的(类型或值初始化为int?)。
Johannes Schaub-litb 2012年

@ JohannesSchaub-litb:嗯,所以也许C ++可以说,如果可以解析一个类型,则首选该类型,否则它是一个表达式。模糊性将得到解决,但sizeof int()会形成不良的(“不operator()size_t”),我希望会是不受欢迎!
史蒂夫·杰索普

32

C99标准

6.5.3.4.2
sizeof操作者产生其操作数的大小(以字节为单位),其可以是表达或类型的括号名称。

就您而言int,既不是表达式也不是带括号的名称。


10
我不明白为什么要这样投票7次。像删除的三个答案一样,它只是重复了规则,而没有解释规则存在的原因。
弗雷德·富

7
@larsmans,是的,我同意你的观点。尽管它继续重复该规则,但是至少,它给出了一些授权阅读。
Yishu Fang

3
@larsmans如果我们开始尝试证明C99中所做的每个决定都是合理的,那么我们将全年待在这里。引用标准与结束本讨论一样是一种好方法。
佩里2012年

1
@Perry:如果您不喜欢这种问题,可以投票关闭该问题,以进行辩论。
弗雷德·富

4
作为非C ++的从业者,即使我理解此答案,也不确定如果您能阅读和理解英语会出现什么问题。
凯夫(Kev)2012年

6

在C中使用sizeof运算符有两种方法。语法是这样的:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

每当使用类型作为操作数时,都必须通过该语言的语法定义加上括号。如果在表达式上使用sizeof,则不需要括号。

C标准给出了这样一个示例,说明您可能希望在表达式上的何处使用它:

sizeof array / sizeof array[0]

但是,为了保持一致性,并避免与运算符优先级相关的错误,我个人建议无论如何都应始终使用()。


@ JohannesSchaub-litb我同意,对于C标准委员会指定C90标准时的推理方式,它没有提供任何依据。您必须要问他们...它的回答没有提供任何理由,但是C不允许这样做,因为语法是在6.5.3中指定的。该OP也似乎没有意识到之间的差别sizeof expressionsizeof(type),这是在这个答案解释。
伦丁2012年

(根据记录,我确实读过C90和C11的基本原理,但都没有提供任何解释。)
Lundin 2012年

我怀疑没有必要的理由,这只是原始C设计师决定这样做的方式。也许它使早期解析器的工作变得更容易。我将发布有关类型定义和变量共享相同名称空间的事实的答案,但这并不排除允许使用第一种语法。它只需要解析规则就可以说,当没有paren时,它更喜欢该变量;当有paren时,它更喜欢该类型;当名称明确时,可以使用任何一种形式。由于不需要更改它,因此标准委员会将其保留。
Barmar 2012年
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.