关于 C 中的 switch{} 情况?
我正在阅读一些 C 语言
文本。文中说 switch{} case
只能接受整数类型。
我只是好奇为什么 switch{} case
不接受其他类型,例如 float 或 string。这背后有什么原因吗?
多谢。
I am reading some text in C language
. The text says that switch{} case
can only accept integer type.
I am just curious about why switch{} case
does not accept other types such as float or string. Are there any reasons behind this?
Thanks a lot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(9)
你必须思考“如何将这段 C 代码转换为汇编语言?”。
switch 条件只是某种棘手的 JMP 指令,顺便说一句,它需要在编译之前对案例进行排序(我猜编译器会对您的案例进行排序),但我不太确定。
例如,在 php 中,您可以使用字符串进行 switch{} 操作,这可能会使用某种二分搜索(它首先查找第一个字符等),就像地图一样。
您必须了解编译语言是生成“相当好的”汇编代码的某种方式,但这并不意味着它会比您仅用汇编语言编写程序更好。
使用像 C 或 C++ 这样的语言,您将能够快速编写程序,并且您的编译器将能够进行琐碎的优化,但看在上帝的份上,使用编程语言时要温和,先考虑一下程序的大局,然后不要忘记语言只是工具,它们并不神奇:如果你忘记了基本的低级行为,你就完蛋了。
浮点值通常不能直接比较
x = 1 / 3.0;
switch (x) {
case 0.3333: /* ... */; break;
case 0.333333333875634875634: /* ... */; break;
case 0.333333333784532452321: /* ... */; break;
case 0.333333333847632874632: /* ... */; break;
default: break;
}
与字符串相同 (no strcpy(buff, "foobar"); if (buff == "foobar") /* ... */;
)
我会回答一个问题:为什么使用 switch 语句而不是 if...else if?
令人惊讶的是,许多程序员从不问这个问题,而是将 switch
视为某些东西语言中必须存在的基础知识。那不是真的!您可以编写任何类型的 C 程序,而无需使用 switch
。严格来说,switch
是一个冗余功能。
那么为什么要使用它呢?
可读性并不是原因。 switch
实际上比 if-else 的语法更糟糕、更不直观。 switch 内部需要break 语句,switch 奇怪的语法规则允许在另一个case 的本地范围内声明一个case,即默认值的任意位置。
switch
不仅可读性较差,而且比 if-else 更容易出现错误。被遗忘的中断是最明显的危险,它导致软件中出现数百万个难以发现的错误。
反对 switch 更具可读性的另一个更明显的论点是这个“裸骨”代码:
if (A)
{
}
else if (B)
{
}
else if (C)
{
}
else
{
}
switch(something)
{
case A:
{
break;
}
case B:
{
break;
}
case C:
{
break;
}
default:
{
break;
}
}
上面的 if 和 switch 在语法和功能上是等效的,并且应该编译为完全相同的机器代码。以下是此示例 switch 的统计信息,
if-else switch
Symbols 33 65 // Not counting the expressions
Lines 12 19 // Not counting empty lines
需要更多代码才能获得相同结果,因此必须将其视为比 if-else 可读性较差。
在你开始争论 switch 看起来更像一个表而不是 if-else 之前,这都是关于代码格式化的,并且是无关紧要的。标准中没有任何内容阻止您编写这样的代码:
if (A) {}
else if (B) {}
else if (C) {}
else {}
switch(something)
{
case A: { break; }
case B: { break; }
case C: { break; }
default: { break; }
}
如果您希望使用某种最小的类似表格的语法,我会认为这两种形式都是可读的。
当然,出于审美、迷信或宗教原因,应该使用 switch 来提高可读性,但我宁愿将这种偏离主题的讨论留给非编程相关的网站。
所以 switch 的安全性和可读性都比 if-else 差。那么剩下的可能对程序员有吸引力的是效率。具有必须由程序测试的 n 个案例的程序员肯定希望有一些东西可以尽快搜索正确的案例。以线性方式检查所有情况是一个坏主意。
您可能知道,通过将 if-else 或 switch 实现为函数指针数组,可以对 if-else 或 switch 进行大量优化:
typedef void (*Func_t)(void);
const Func_t cases [N] = { ... };
cases[i]();
这种彻底的优化通常正是编译器在遇到 switch 语句时所做的事情。然而,这种优化只有在所有情况都是相邻整数的情况下才能完成。如果它们不相邻,则可以通过 const 查找表创建邻接关系。
但如果case不是整数类型,则无法进行上述优化。如果它们是浮点数、字符串或其他东西,则没有明智的方法来优化代码。
因此,至少在我的书中,switch
仅出于此目的而存在:它使编译器更容易创建比 if-else 更有效的代码。因此,它与关键字 inline、register 等属于同一类别,这也使编译器更容易优化代码。
经典的原因可能是对于整数值的“决策表达式”,可以进行非常好的优化。
基本上,您可以将 case 语句列表映射到包含地址的表,然后根据值直接跳转。显然,对于浮点数和字符串来说这是行不通的。
在 GCC 中,您可以使用 some 手动执行此操作像这样的扩展:
const char * digit_name(int d)
{
const void * handlers[] = { &&zero, &&one, &&two, &&three, &&four,
&&five, &&six, &&seven, &&eight, &&nine };
goto *handlers[d]; /* Assumes d is in range 0..9. */
zero: return "zero";
one: return "one";
two: return "two";
three: return "three";
four: return "four";
five: return "five";
six: return "six";
seven: return "seven";
eight: return "eight";
nine: return "nine";
return NULL;
}
这通常称为“计算的转到”,并且应该清楚如何将 switch
基本上编译为非常相似的东西。打开表达式的严格定义会有所帮助,例如使用enum
。
此外,C 在语言级别上并没有太多字符串的概念。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
当有多个选项时,开关可能是最佳选择。编译器可以警告您重复的情况,如果您使用枚举,好的编译器会警告您未处理的值。
作为一个好的实践,浮点数/双精度数不应该测试相等性,“if(f = 3.141516)”会让人头疼,“const float kEpsilon = 1e-5;”然后使用“if(fabs(f - 3.141516) < kEpsilon)”
选择与您的问题相关的 epsilon 值。内联函数或宏可能有助于以更具可读性的方式编写此内容。
A switch is probably the best choice when there is a discrete number of options. The compiler can warn you about duplicate cases and if you use enums good compiler will warn about values not handled.
As a good practice floats/doubles should not tested for equality, "if(f = 3.141516)" is an invitation for headaches, "const float kEpsilon = 1e-5;" and then use "if(fabs(f - 3.141516) < kEpsilon)"
Pick an epsilon value that is relevant for your problem. An inline function or macro may help to write this in a more readable way.