案例标签不需要空格?

时间:2015-02-26 17:23:46

标签: c++ c switch-statement

可能这是一个愚蠢的问题,但有没有人知道case关键字与switch语句中的常量表达式之间是否存在必填空格?

标准似乎没有说明......

请考虑以下代码:

switch(int_expression)
{
    case1:     /*anything*/  // no space before 1
    caseZERO:  /*anything*/  // no space before ZERO
                             // ZERO being defined as 0
                             // by the pre-processor
}

我的参考编译器都接受这个代码,一旦运行它就可以正常工作。 预处理器如何识别ZERO必须被替换?

另请注意,如果控件表达式是char类型而不是int类型,则还会编译以下内容,但这次它不再有效

switch(char_expression)
{
    case'a':   /* anything */  // NO SPACES embedded
    caseZERO:  /* anything */  // NO SPACES again
                               // ZERO being defined as '0'
                               // by the pre-processor
}

这个编译,但即使char_expression的值为'0' caseZERO中没有声明被执行。

任何人都能解释一下吗?

2 个答案:

答案 0 :(得分:8)

这些是与goto一起使用的常规标签,并不会按照您的意图实际匹配表达式。语法有效,但语义不同。

您没有指定这是C编译器还是C ++编译器,所以这里也是C语言中goto的文档。

另外,如果您查看附录A.2.3(6.8.1)中ISO C标准提供的实际语法,则定义标记语句,如下所示:

  

(6.8.1)标签声明:

     

标识符 声明

     

案例 常量表达式 声明

     

默认 声明

特别注意case是一个单一的标记,在语法的上下文中必须至少有一个标记分隔字符。 case1示例中的数字不算作标记分隔字符,因此您的示例属于语法的第一个分支,即标识符 case语句,因此不能用作switch语句的目标。

要回答有关在预处理器宏中定义ZERO的其他问题,您认为替换不会发生。同样,预处理器对令牌进行操作,因此caseZERO是与ZERO宏不匹配的单个令牌,因此根本不会被替换。同样,这只是使用标识符分支定义标记语句,其中标识符是整个标记caseZERO而不是case0或{{ 1}}如你所愿。预处理器确实有使用case'0'运算符进行“令牌粘贴”的方法,但这需要您使用##。但是,这仍然没有您可能想要的行为。

答案 1 :(得分:3)

案例表达式的类型无关紧要。它是重要的句法形式。

switch (expr) {
    caseZERO: /*...*/;
    case0:    /*...*/;
    case'a':  /*...*/;
}

caseZEROcase0都是有效的标识符。在此上下文中,它们是标签,但不是 case标签。如果您有声明

 goto caseZERO;

 goto case0;

在同一个函数中,它将分支到相应的带标签语句。

(这是C语言中的众多案例之一,其中拼写错误导致代码在语法上仍然有效,但意义却截然不同。)

另一方面,

case'a'两个标记,因为'a'字符常量。 (但为了人类读者的利益,它仍应写成case 'a':。)

将源代码拆分为标记的规则要求标识符,关键字或数字文字与另一个标识符,关键字或数字文字之间有空格,否则它将是不明确的。他们在其他环境中需要空格。这就是为什么,例如,你可以写:

 x=y+func(42);

而不是

 x = y + func ( 42 ) ;

添加一些空白区域将使代码对人类读者更易读:

x = y + func(42);

但是编译器并不关心。

(空格很重要的另一种情况是函数式宏的定义。(必须紧跟宏名称;否则它被视为扩展的第一个标记,而不是介绍参数列表。)