C和C++中的花括号

20

为什么这段代码能编译通过:

int main() 
{
    {}  
}

但这不会:

    {}

int main() 
{  
}
4个回答

33

第一种情况,你正在函数内定义一个块,这是允许的(它可以限制能见度)。 第二种情况,你正在定义一个匿名块,这是不允许的(它需要在函数定义之前,否则编译器将永远不知道何时执行它)


20

{} 是一个无操作语句(在C语法中它是一个空的复合语句)。您可以在函数中放置语句,但不能在其他地方放置语句。

我想标准没有禁止在您的第一个示例中使用空语句的原因是虽然它是无意义的,但它没有害处,并且为何要引入允许花括号为空时的规则只会增加复杂度而没有任何益处。

严谨地说,语法也没有定义文件范围的任何其他构造,其中 {} 是有效实例,这就是为什么第二个示例无效的原因。


7
@Acme:Steve的回答是针对C语言的。对于C++,答案类似:在函数定义中,包括 {} 的语句是有效的。没有其他地方允许语句出现。{} 还有其他用途(命名空间、类、结构体、联合体、枚举、初始化器、链接规范),但所有这些用法都需要更多的标识符来形成有效的语法,而不仅仅是 {} - aschepler
空的复合语句可能是由于宏定义而被允许。由于宏可以扩展为空,所以简单的 { DBG("Hello"); }DBG 被扩展为空时将无法编译通过,这会令人惊讶。 - Matthieu M.
@Matthieu:我考虑过这个问题,但是当assert宏被禁用时,它不会产生任何结果,而是产生(void)0或类似的结果。而你的DBG宏并不会产生一个空的复合语句{},而是会产生{;}:一个包含空语句的复合语句。当然,有时候拥有空的复合语句是很有用的,而宏就是一个例子,但是考虑到assert的定义,我不想说标准委员会期望人们编写最终扩展为空的宏,因为他们自己避免了这种情况。 - Steve Jessop
所以,由于我想不出一个明确需要空复合语句的例子,因此我坚持认为“没有禁止它们的必要性”是我的建议理由 :-) - Steve Jessop
1
@Acme:正如@achepler所说,我的回答也适用于C++,在C++语法中没有任何东西使得{}在文件作用域上是有效的。命名空间定义以关键字namespace和可选名称开头,因此在此之后{}是有效的,但不能单独使用。同样,在C++中,struct foo {};是有效的,但这也不意味着仅使用{}是有效的。在C和C++中,void foo() {}是有效的 - 同样,这并不允许没有引言的{} - Steve Jessop
@Steve:我应该在宏内部包含;!不这样做的原因显然是为了不搞乱一行代码:当DBG扩展为空时,带有嵌入式;while(--i) DBG(x[i])将会让每个人都感到惊讶!另一方面,将宏扩展为(void)0,即使被优化掉,宏仍然扩展为一个正确的语句。 - Matthieu M.

5

由于全局范围中定义的代码在C中是不允许的。请记住,在C中,除了变量声明/初始化之外的每行代码都必须位于函数内部。

如果您在函数内部,则可以拥有所有想要的{}块。


包含/定义也可以在函数外部使用。 - BlackBear
6
@BlackBear说得没错,但是它们并不是C语句。它们只是宏预处理器。 - Pablo Santa Cruz

3

因为在翻译单元的顶层只能出现声明或函数定义,不能出现复合语句(无论是否为空)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接