切换案例标签中的C11和常量表达式评估

时间:2018-05-24 13:38:48

标签: c++ c switch-statement constants constant-expression

关注此问题Why doesn't gcc allow a const int as a case expression?,与What promoted types are used for switch-case expression comparison?Is there any way to use a constant array with constant index as switch case label in C?基本相同。

从第一个链接开始,我尝试替换:

case FOO:                       // aka 'const int FOO = 10'

with:

case ((int) "toto"[0]):         // can't be anything *but* constant

给出了:

https://ideone.com/n1bmIb - > https://ideone.com/4aOSXR =适用于C ++

https://ideone.com/n1bmIb - > https://ideone.com/RrnO2R =在C

中失败

我不太明白,因为" toto" string不能是但是是一个常量,它甚至不是一个变量,它位于编译器内存的空白之中。我甚至没有玩过' const' C语言的模糊逻辑(实际上代表"只读,不是常数,你期望什么?"),问题是"数组访问"或"指针引用"转换为不在C中求值的常量表达式,但在C ++中表现很好。

我希望用这个"技巧"使用HASH_MACRO(str)从密钥标识符生成唯一的case标签值,最终使编译器在发生冲突时引发错误,因为找到了类似的标签值。

好的,好的,我被告知这些限制是为了简化语言工具(preproc,编译器,链接器)和C ain没有LISP,但你可以拥有全功能的LISP解释器/编译器,只需一小部分C等价物的大小,所以没有任何借口。

问题是:是否有"扩展"到C11只允许这个" toto"在GCC,CLANG和... MSVC工作?我不想去C ++路径(typedef'前向声明不再工作)和嵌入式东西(因此编译时哈希计算用于时空失真)。

是否有中间人" C +"更加宽容的语言'并且“了解'嵌入式更好一点,比如-Praise the Lords-" enums as bitfield members&#34 ;,在我们不能拥有的其他很好的东西中(因为现实标准像沙漠太阳下的蜗牛一样发展)?

#provemewrong,#changemymind,#norustplease

3 个答案:

答案 0 :(得分:6)

在编译时编译器是否可以知道它并不重要。 case标签需要具有整数常量表达式 (C11 6.8.4.2p3)的值。

  
      
  1. 每个case标签的表达式应为整数常量表达式,并且同一switch语句中的两个case常量表达式在转换后不应具有相同的值。 switch语句中最多可能有一个默认标签。 (任何封闭的switch语句都可以有一个默认的标签或case常量表达式,其值可以在封闭的switch语句中复制case常量表达式。)
  2.   

整数常量表达式的定义是in C11 6.6p6

  
      
  1. 整数常量表达式应具有整数类型,并且只能具有整数常量的操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,_Alignof表达式和浮动常量是演员的直接操作数。整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof_Alignof运算符的操作数的一部分。
  2.   

由于"toto"不是整数常量,枚举常量,字符常量,常量sizeof_Alignof表达式或浮点常量强制转换为整数;并且该列表在标准的约束部分中指定,编译器不能以静默方式传递。 (即使是符合标准的编译器仍然可以成功编译程序,但它必须将其诊断为违反约束。)

您可以使用链接? :来将索引解析为字符常量,即

  x == 0 ? 't' 
: x == 1 ? 'o'
: x == 2 ? 't'
: x == 3 ? 'o'

这可以写入宏。

答案 1 :(得分:2)

"toto[0]"不是整数常量表达式,因为C定义了术语:

6.6常量表达式
...
6整数常量表达式 117)应具有整数类型,并且只能有操作数 它是整数常量,枚举常量,字符常量, sizeof 结果为整数常量, _Alignof 表达式和浮点数的表达式 作为强制转换的直接操作数的常量。将运算符转换为整数常量 expression只能将算术类型转换为整数类型,除非作为一部分 操作数为 sizeof _Alignof 运算符。 117)在许多上下文中需要整数常量表达式,例如位域的大小 结构的成员,枚举常量的值和非可变长度的大小 阵列。适用于条件包含中使用的整数常量表达式的其他约束 预处理指令在6.10.1。中讨论

C 2011 online draft

答案 2 :(得分:0)

你遇到的问题是,在C中,“toto”是一个字符数组。当然,它在内存中是恒定的,但它仍然只是一个数组。 []运算符在数组中索引(来自指针)。如果您愿意,您可以编辑已编译的二进制文件并将字符串“toto”更改为其他内容。从某种意义上说,它不是编译时知道的。这相当于:

char * const ___string1 = "toto";
...
case ((int) ___string1[0]):

(这有点强迫和多余,但它仅用于演示)

请注意,字符串文字的元素类型为char,而不是const char

这种情况必须是常量,因为它内置于编译的程序控制流程中。