在C语言中,switch和字符串字面字符

3

看下面的例子:

int main(){
        char *s = "Hello";
        switch (s[0]) {
                case "Hello"[0]:
                        return 1;
                case "Goodbye"[0]:
                        return 2;
                default:
                        return 0;
        }
}

当编译这个示例时,我收到一个错误,它抱怨case标签不是整数。但是这似乎是不正确的,因为"..."[0]解析为整数。 有人能够解释一下为什么这段代码不能编译吗?

1
我的直觉告诉我它不会成为一个编译时整数常量。 - user7116
我也需要对这个问题进行解释。"Goodbye"[0] 看起来确实是 'G' - Rüppell's Vulture
3个回答

6
案例标签需要是一个整数常量,而不是一个整数表达式。虽然表达式"Hello" [0]可以在编译时求值为'H',但编译器并不一定要这样做。
引用: C99标准,第6.8.4.2节,第3部分: 每个案例标签的表达式都应该是一个整数常量表达式,在同一个switch语句中,两个案例常量表达式在转换后的值不应该相同。

编译器不一定需要这样做。这是否仅适用于case标签,还是整个C中的编译时评估都是可选的? - seininn
但是"Goodbye"[0]不是字符常量**'G'吗?毕竟,"Goodbye"给出了字符串常量**Goodbye的基地址,而"Goodbye"[0]就是**'G'**。你能解释一下为什么它仍然会出错吗?我的意思是为什么case 'G':可以工作,但这个却不行。 - Rüppell's Vulture
2
"Goodbye"[0] 是一个涉及多个步骤的计算结果:分配一些内存,将字符串 "Goodbye" 放入其中,生成指向它的指针,并加载指针所指向的字符。从概念上讲,最后一步只能在运行时发生,因为它需要程序的运行实例来执行加载操作。整数常量不能包含任何运行时操作,即使结果在理论上是可预测的。(int)(4*atan2(1,1)) 可以预测会评估为 3,但最好不要尝试将其用作 case 标签。 - user2404501
@WumpusQ.Wumbley,你提供的理由足够充分,很容易让人相信。不过,我们还是听听 dasblinkenlight 的意见吧。 - Rüppell's Vulture
@Rüppell'sVulture WumpusQ.Wumbley 是正确的,计算 "Goodbye"[0] 的值需要分配 "Goodbye" 并获取字符串字面量的初始地址处的值,这不被视为编译时常量。 - Sergey Kalinichenko

0
"

"Hello"是一个字符串字面量。如果你想要字符串字面量的第一个字符,那么你需要指定它,即'H',它是一个单一字符。

case语句只能是整数或者可以转换为整数的类型,并且必须是常量。

请参考这篇关于switch语句的教程。进入链接描述在此处

"

0

case标签应该是常量表达式,可以在编译时进行评估。 虽然看起来很合理,但使用常量索引访问字符串字面值并不是常量表达式。

这涉及到C(++)的类型系统。每个表达式都有一个静态类型。对于字符串字面值,它是const char[],而对于任何数组,其值是指针,无法在编译时知道。 它在链接时填充(考虑消除重复字符串字面值的优化),如果全局优化无法解决,则最可能在生成的代码中找到间接引用。


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