在浏览解析器的代码时,例如Parser.cpp里面clang编译器的clang / Parse目录
switch (Close) {
default: break;
case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
case tok::greatergreatergreater:
LHSName = "<<<"; DID = diag::err_expected_ggg; break;
}
我看到default
刚开始。是否有任何理由保持这种方式。通常我们会将default
保留在最后,所以我有点困惑。
答案 0 :(得分:1)
只要您添加了break
s。
顺便说一句,我希望在每个break
或case
之前立即将<{1}}放在之前。验证遵循此规则比尝试展望每个案例陈述的结尾要容易得多。
default
如果您将switch (Close) {
break; default:
break; case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen;
break; case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace;
break; case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare;
break; case tok::greater: LHSName = "<"; DID = diag::err_expected_greater;
break; case tok::greatergreatergreater: LHSName = "<<<"; DID = diag::err_expected_ggg;
}
解释为“请勿通过进入此案例来自任何其他情况。”,您可能会更容易理解这一点“不要通过从这个案例落入任何后续案例。”
在这种布局中,很容易看出是否缺少break
,因此迫使作者(和读者)问他/她“我想要在这里进行跟进吗?”。所有的break
都很好地排队,如果缺少一个就很明显。
break
最后的break
是多余的。如果缺少,则不允许编译器循环到switch
的顶部,就好像它是某种switch
循环一样。同样,while
开头的冗余break
不会发生任何变化,编译器必须接受(并忽略)。
答案 1 :(得分:0)
我唯一一次看到默认事项的位置就是做这样的事情,这是Duff's Device类型的构造,应该永远不会在现代平台上尝试。 :)
void copyAligned4Bytes(u32 *in, u32 *out, int numBytes)
{
assert((numBytes & 0x03) == 0);
while(numBytes)
{
switch(numBytes)
{
default: *out++ = *in++; numBytes -= 4;
case 12: *out++ = *in++; numBytes -= 4;
case 8: *out++ = *in++; numBytes -= 4;
case 4: *out++ = *in++; numBytes -= 4;
}
}
}
啊,在C中编码的乐趣尽可能接近汇编程序以获得某种类型的跳转表。