为什么空语句合法?

发布于 2024-07-19 14:48:55 字数 322 浏览 10 评论 0原文

int main()
{
    int var = 0;; // Typo which compiles just fine
}

在 C 和 C++ 中,这是允许的,因为 表达式-statement 可能只是一个 ;,这使其成为“空语句”。 为什么这是允许的?

int main()
{
    int var = 0;; // Typo which compiles just fine
}

In both C and C++, this is allowed because an expression-statement may be just a ;, which makes it a "null statement". Why is this allowed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

月隐月明月朦胧 2024-07-26 14:48:55

当定义了 NDEBUG 时,assert(foo == bar); 怎样才能编译成空呢?

How else could assert(foo == bar); compile down to nothing when NDEBUG is defined?

浮萍、无处依 2024-07-26 14:48:55

你希望能够做类似

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);

这是一个很好的方式来迷惑读者,因为它很容易错过了分号,因此认为下一行是循环体。 请记住:编程实际上是关于沟通——不是与编译器的沟通,而是与其他将阅读您的代码的人的沟通。 (或者三年后的你自己!)

You want to be able to do things like

while (fnorble(the_smurf) == FAILED)
    ;

and not

while (fnorble(the_smurf) == FAILED)
    do_nothing_just_because_you_have_to_write_something_here();

But! Please do not write the empty statement on the same line, like this:

while (fnorble(the_smurf) == FAILED);

That’s a very good way to confuse the reader, since it is easy to miss the semicolon, and therefore think that the next row is the body of the loop. Remember: Programming is really about communication — not with the compiler, but with other people, who will read your code. (Or with yourself, three years later!)

十级心震 2024-07-26 14:48:55

我不是语言设计师,但我给出的答案是“为什么不呢?” 从语言设计的角度来看,希望规则(即语法)尽可能简单。

更不用说“空表达式”还有用途,即

for (i = 0; i < INSANE_NUMBER; i++);

将死等(不是一个好的用途,但仍然是一个用途)。

编辑:正如对此答案的评论中所指出的,任何有价值的编译器都可能忙于等待这个循环,并将其优化掉。 但是,如果 for 头本身(除了 i++ 之外)有更有用的东西,我已经看到(奇怪地)通过数据结构遍历完成了,那么我想你仍然可以构造一个带有空主体的循环(通过使用/滥用“for”结构)。

I'm no language designer, but the answer I'd give is "why not?" From the language design perspective, one wants the rules (i.e. the grammar) to be as simple as possible.

Not to mention that "empty expressions" have uses, i.e.

for (i = 0; i < INSANE_NUMBER; i++);

Will dead-wait (not a good use, but a use nonetheless).

EDIT: As pointed out in a comment to this answer, any compiler worth its salt would probably not busy wait at this loop, and optimize it away. However, if there were something more useful in the for head itself (other than i++), which I've seen done (strangely) with data structure traversal, then I imagine you could still construct a loop with an empty body (by using/abusing the "for" construct).

一枫情书 2024-07-26 14:48:55

这是 C 和 C++ 表达 NOP 的方式。

This is the way C and C++ express NOP.

桃酥萝莉 2024-07-26 14:48:55

好的,我会将其添加到您可能实际使用的最坏情况场景中:

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:;
    }
}   

OK, I’ll add this to the worst case scenario that you may actually use:

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:;
    }
}   
猫卆 2024-07-26 14:48:55

使用;时,还请注意一件事。 这是可以的:

a ? b() : c();

但是这不会编译:

a ? b() : ; ;

When using ;, please also be aware about one thing. This is ok:

a ? b() : c();

However this won't compile:

a ? b() : ; ;
撞了怀 2024-07-26 14:48:55

已经有很多好的答案,但还没有看到生产环境样本。

这里是 FreeBSD 对 strlen 的实现:

size_t
strlen(const char *str)
{
    const char *s;

    for (s = str; *s; ++s)
        ;
    return (s - str);
}

There are already many good answers but have not seen the productive-environment sample.

Here is FreeBSD's implementation of strlen:

size_t
strlen(const char *str)
{
    const char *s;

    for (s = str; *s; ++s)
        ;
    return (s - str);
}
帝王念 2024-07-26 14:48:55

显然,这样我们就可以说诸如“

for (;;) {
  // stuff
}

没有它谁能活下去?”之类的话。

Obviously, it is so that we can say things like

for (;;) {
  // stuff
}

Who could live without that?

旧城烟雨 2024-07-26 14:48:55

老实说,我不知道这是否是真正的原因,但我认为更有意义的是从编译器实现者的角度来考虑它。

大部分编译器是由分析特殊语法类别的自动化工具构建的。 有用的语法允许空语句似乎是很自然的。 当它不改变代码的语义时,检测这样的“错误”似乎是不必要的工作。 空语句不会执行任何操作,因为编译器不会为这些语句生成代码。

在我看来,这只是“不要修复未损坏的东西”的结果......

I honestly don't know if this is the real reason, but I think something that makes more sense is to think about it from the standpoint of a compiler implementer.

Large portions of compilers are built by automated tools that analyze special classes of grammars. It seems very natural that useful grammars would allow for empty statements. It seems like unnecessary work to detect such an "error" when it doesn't change the semantics of your code. The empty statement won't do anything, as the compiler won't generate code for those statements.

It seems to me that this is just a result of "Don't fix something that isn't broken"...

醉酒的小男人 2024-07-26 14:48:55

最常见的情况可能是

int i = 0;
for (/* empty */; i != 10; ++i) {
    if (x[i].bad) break;
}
if (i != 10) {
    /* panic */
}

The most common case is probably

int i = 0;
for (/* empty */; i != 10; ++i) {
    if (x[i].bad) break;
}
if (i != 10) {
    /* panic */
}
婴鹅 2024-07-26 14:48:55
while (1) {
    ;  /* do nothing */
}

有时候你想坐下来什么也不做。 事件/中断驱动的嵌入式应用程序或当您不希望函数退出时(例如在设置线程并等待第一次上下文切换时)。

例子:
http://lxr.linux.no/ linux+v2.6.29/arch/m68k/mac/misc.c#L523

while (1) {
    ;  /* do nothing */
}

There are times when you want to sit and do nothing. An event/interrupt driven embedded application or when you don't want a function to exit such as when setting up threads and waiting for the first context switch.

example:
http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文