使用大括号的Case语句

3
为什么case语句允许在花括号内部进行声明,而在外部则不行?
例如,以下语句是不正确的。
switch (op->name) {
    case 0:
        int a = 2;
    case 1:  
        int b = 3;
}

但是下面这个是可以的:

switch (op->name) {
    case 0: 
       {int a = 2;}
    case 1:  
       {int b = 3;}
}

没有花括号,编译器在声明时会出现歧义。对于我(一个C语言初学者)来说,似乎每个case语句应该有一个隐含的花括号,直到下一个case/default/end-of-switch出现,但这显然是错误的!

1
在C语言中,变量必须在块的开头声明。花括号开始一个新的块。case标签不会创建“隐含的花括号”。 - Raymond Chen
2
在C语言中,变量必须在块的开头声明。@RaymondChen 这是C89的规则。但在C99及以后的版本中不再适用。 - user3386109
@samuelbrody1249 在代码片段2和3中,switch语句后面确实需要一个左花括号。 - user3386109
@user3386109 抱歉,那是个打错字了 -- 已经修正。 - samuelbrody1249
@user3386109 是的,看起来出现了错误,我想大括号不能超出单个 case。无论如何,我已经从问题中删除了该 case,因为它是错误的。 - samuelbrody1249
显示剩余3条评论
3个回答

5
为什么在case语句中可以使用带花括号的声明,但是没有花括号就不行呢?
我的编译器会输出这个错误消息:
error: a label can only be part of a statement and a declaration is not a statement

我觉得很清楚。标签(包括case标签)不被视为独立的语句或声明,而是语句的组成部分。当控制流跳转到标签时,无论是通过switch还是goto,程序都会跳转到包含该标签的语句。通常情况下,标签本身没有运行时表示。

int a;这样的声明不是语句,标签不能作为声明的一部分。另一方面,诸如{ int a; }之类的块是语句,因此它们可以有标签。

这里没有根本性的限制。实际上,C语法可以定义得不同,使得两个示例都有效。只是没有这样定义。


3
这是无效的原因:
switch (op->name) {
    case 0:
        int a = 2;
    case 1:  
        int b = 3;
}

这是因为您在声明前有一个标签(在此处是一个case标签)。 标签只能出现在语句前面。

使用大括号的原因是它们用于表示复合语句,这是一种特定类型的语句,语句可以紧接着标签。

形式上,标签是带标签的语句的一部分。详见C标准的6.8.1节:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

labeled-statement:
  identifier : statement
  case constant-expression : statement
  default : statement

谢谢。identifier : statement 的一个例子是什么? - samuelbrody1249
1
@samuelbrody1249 这是一个“常规”标签,可以作为goto的主题。 - dbush

1

尝试这样做,你将不会收到错误:

switch (op->name) {
    case 0:; /* <--- that ; is essential, see below */
        int a = 2;
    case 1:; /* <--- the same here. */
        int b = 3;
}

问题在于,case 语句语句的一种特殊情况,但是声明不能替代语句,因此在case标签之后不允许使用声明。但是您可以始终以分号结束case_statement(发出null statement),然后在其后放置您的声明。

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