int main()
{
int var = 0;; // Typo which compiles just fine
}
在 C 和 C++ 中,这是允许的,因为 表达式语句 可能只是一个
;
,这使其成为“空语句”。为什么允许这样做?
当定义了
assert(foo == bar);
时,NDEBUG
怎样才能编译为空?
这就是C和C++的表达方式NOP。
您希望能够做类似的事情
while (fnorble(the_smurf) == FAILED)
;
而不是
while (fnorble(the_smurf) == FAILED)
do_nothing_just_because_you_have_to_write_something_here();
但是! 请不要在同一行写空语句,如下所示:
while (fnorble(the_smurf) == FAILED);
这是一个很好的方法来迷惑读者,因为很容易错过分号,从而认为下一行是循环体。请记住:编程实际上就是沟通——不是与编译器沟通,而是与其他会阅读您代码的人沟通。 (或者三年后的你自己!)
我不是语言设计师,但我给出的答案是“为什么不呢?”从语言设计的角度来看,希望规则(即语法)尽可能简单。
更不用说“空表达式”还有用途,即
对于 (i = 0; i < INSANE_NUMBER; i++);
将等待(不是一个很好的用途,但仍然有用)。
编辑:正如对此答案的评论所指出的,任何有价值的编译器都可能not忙于等待这个循环,并优化它。但是,如果 for 头本身(除了 i++ 之外)有更有用的东西,我已经看到(奇怪地)通过数据结构遍历完成了,那么我想你仍然可以构造一个带有空主体的循环(通过使用/滥用“for”结构)。
好的,我会将其添加到您可能实际使用的最坏情况场景中:
for (int yy = 0; yy < nHeight; ++yy) {
for (int xx = 0; xx < nWidth; ++xx) {
for (int vv = yy - 3; vv <= yy + 3; ++vv) {
for (int uu = xx - 3; uu <= xx + 3; ++uu) {
if (test(uu, vv)) {
goto Next;
}
}
}
Next:;
}
}
老实说,我不知道这是否是真正的原因,但我认为更有意义的是从编译器实现者的角度来考虑它。
大部分编译器是由分析特殊语法类别的自动化工具构建的。有用的语法允许空语句似乎是很自然的。当它不改变代码的语义时,检测这样的“错误”似乎是不必要的工作。空语句不会执行任何操作,因为编译器不会为这些语句生成代码。
在我看来,这只是“不要修复未损坏的东西”的结果......
显然,我们可以这样说
for (;;) {
// stuff
}
没有它谁能活下去?
使用
;
时,还请注意一件事。这样就可以了:
a ? b() : c();
但是这不会编译:
a ? b() : ; ;
已经有很多好的答案,但还没有看到生产环境样本。
这里是FreeBSD对
strlen
的实现:
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
最常见的情况可能是
int i = 0;
for (/* empty */; i != 10; ++i) {
if (x[i].bad) break;
}
if (i != 10) {
/* panic */
}
while (1) {
; /* do nothing */
}
有时候你想坐下来什么也不做。事件/中断驱动的嵌入式应用程序,或者当您不希望函数退出时,例如在设置线程并等待第一次上下文切换时。
示例: http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523