Why sizeof int is wrong, while sizeof(int) is right?
我们知道sizeof是用于计算任何数据类型和表达式的大小的运算符,并且当操作数是表达式时,可以省略括号。
1 2 3 4 5 6 7 8 9 10 11
| int main()
{
int a;
sizeof int;
sizeof( int );
sizeof a;
sizeof( a );
return 0;
} |
sizeof的首次用法是错误的,而其他用法是正确的。
使用gcc进行编译时,将显示以下错误消息:
1
| main.c:5:9: error: expected expression before ‘int’ |
我的问题是,为什么C标准不允许这种操作。 sizeof int会引起歧义吗?
-
有趣的是,并非所有表达式都没有括号就可以接受:请尝试sizeof (int)a。
-
@MikkelK .: OP正在询问标准语录背后的推理,他已经知道标记答案中提到的语录。
-
@larsmans我猜那是因为在sizeof之后的括号被解释为sizeof运算符的一部分,而不是属于表达式其余部分的东西(本来是类型转换运算符)。因此,如果我正确理解这一点,那么您可能会编写诸如sizeof *&(int)a之类的晦涩难懂的文字,因为我们最终使用的是表达式而不是类型,所以就可以了。
-
@Lundin:sizeof +(int)a优于*&的实际编译优势;-)
-
@SteveJessop嗯,不是左值。尽管它确实是在Embarcadero C ++中编译的,但奇怪的是。无论如何,我相信我们刚刚发现了一元+运算符的用法!那一定是C编程历史上的第一次:)
-
@Lundin:一元+仍然要小心。例如,sizeof +(char)a == sizeof(int)由于整数提升,如果完全担心您要采用的大小的表达式,则只需将其放在括号中可能不太容易出错。因此,我不确定自己是否能将其称为"一种用途",尽管我承认我确实使用过它……
-
@SteveJessop确实。所有这些对于IOCCC都是极好的材料,但对于现实生活的代码而言可能不是:)
-
让我们继续聊天中的讨论
以下可能是模棱两可的:
是(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可能具有相同的限制,我不
-
如果C ++未指定new运算符采用可能是类型的最长字符串,则C ++具有new int*(X)可能会模棱两可。因此,我想在C ++中,它们可以使用sizeof进行相同的处理。但是在C ++中,您可以说sizeof int(),这将是模棱两可的(类型或值初始化为int?)。
-
@ JohannesSchaub-litb:嗯,所以也许C ++可以说如果可以解析一个类型,则首选该类型,否则可以是一个表达式。歧义可以解决,但sizeof int()格式不正确("对于size_t,没有operator()"),我希望这是不受欢迎的!
从C99标准
6.5.3.4.2
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a
type.
在您的情况下,int既不是表达式也不是括号名称。
-
我不明白为什么这会得到7票赞成。像删除的三个答案一样,它只是重复了规则,而没有解释规则存在的原因。
-
@larsmans,是的,我同意你的观点。尽管它继续重复该规则,但是至少,它给出了一些授权阅读。
-
@larsmans如果我们开始尝试证明C99中所做的每个决定都是合理的,那么一年四季都在这里。引用标准与结束本讨论一样是一种好方法。
-
@Perry:如果您不喜欢这种问题,可以投票关闭该问题。
-
作为非C ++的从业者,即使我理解此答案,也不确定如果您能阅读和理解英语会出现什么问题。
-
+1使我感到困惑的是int;编译;所以我错误地认为它也必须是一个表达式。看一下您引用的标准后,结果发现存在一些语法规则(6.7):declaration: declaration-specifiers init-declarator-list[opt] ;,declaration-specifiers: type-specifier declaration-specifiers[opt]和type-specifier: int将int;定义为声明,而不是表达式([opt ]表示可选)。感谢您的报价和链接的文档。
在C中使用sizeof运算符有两种方法。语法是这样的:
1 2 3 4
| C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name ) |
每当使用类型作为操作数时,都必须通过该语言的语法定义加上括号。如果在表达式上使用sizeof,则不需要括号。
C标准给出了这样一个示例,说明您可能希望在表达式上的何处使用它:
1
| sizeof array / sizeof array[0] |
但是,为了保持一致性,并避免与运算符优先级相关的错误,我个人建议无论如何都应始终使用()。
-
@ JohannesSchaub-litb我同意,对于C标准委员会在指定C90标准时的推理方式,它没有提供任何依据。您必须要问他们...它的回答没有提供任何理由,但是C不允许这样做,因为语法是在6.5.3中指定的。 OP似乎也没有意识到sizeof expression和sizeof(type)之间的区别,对此答案进行了解释。
-
(出于记录目的,我确实阅读了C90和C11的基本原理,但均未提供任何解释。)
-
我怀疑没有必要的理由,这只是原始C设计师决定这样做的方式。也许它使早期解析器的工作变得更容易。我将发布有关类型定义和变量共享相同名称空间的事实的答案,但这并不排除允许使用第一种语法。它只需要解析规则就可以说,当没有paren时,它偏爱变量;当有paren时,它偏爱类型;当名称明确时,可以使用任何一种形式。由于不需要更改它,因此标准委员会将其保留。