C语言 while(1)的目的;C中的语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24278724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:11:06  来源:igfitidea点击:

Purpose of while(1); statement in C

cwhile-loop

提问by Abhijit K Rao

What purpose does while(1);serve ? I am aware while(1)(no semicolon) loops infinitely and is similar to a spinlock situation. However I do not see where while(1);could be used ?

有什么目的while(1);?我知道while(1)(没有分号)无限循环并且类似于自旋锁情况。但是我不知道在哪里while(1);可以使用?

Sample code

示例代码

if(!condition)
{ 
  while(1);
}

Note: This is not a case of do-while()or plain while(1).

注意:这不是do-while()或普通的情况while(1)

回答by dureuill

Please note that all valid statements of the language do not have toserve a purpose. They are valid per the grammar of the language. One can build many similar "useless" statements, such as if (1);. I see such statements as the conjunction of a conditional (if, while, etc.) and the empty statement ;(which is also a valid statement although it obviously serves no specific purpose).

请注意语言的所有有效的声明并不具有服务于一个目的。它们根据语言的语法是有效的。可以构建许多类似的“无用”语句,例如if (1);. 我看到诸如条件(ifwhile等)和空语句;(这也是一个有效语句,尽管它显然没有特定目的)的连接这样的语句。

That being said, I encountered while (1);in security code. When the user does something very bad with an embedded device, it can be good to block them from trying anything else. With while (1);, we can unconditionally block a device until an accredited operator manually reboots it.

话虽如此,我while (1);在安全代码中遇到了。当用户使用嵌入式设备做了一些非常糟糕的事情时,阻止他们尝试其他任何事情可能会很好。使用while (1);,我们可以无条件地阻止设备,直到经过认证的操作员手动重新启动它。

while(1);can also be part of the implementation of a kernel panic, although a for(;;) {}loop seems to be a more common way of expressing the infinite loop, and there might be a non-empty body (for instance to panic_blink()).

while(1);也可以是内核恐慌实现的一部分,尽管for(;;) {}循环似乎是表达无限循环的更常见方式,并且可能存在非空主体(例如 to panic_blink())。

回答by a.atlam

If you dig down to assembly, (this is easier to grasp from an embedded systems point of view, or if you tried to program a bootloader)

如果您深入到组装,(从嵌入式系统的角度来看,这更容易掌握,或者如果您尝试对引导加载程序进行编程)

you will realize that a while loop is just a jmp instruction ... ie

你会意识到 while 循环只是一个 jmp 指令......即

(pseudo code: starting loop address)
add ax, bx
add ax, cx
cmp ax, dx
jz  (pseudo code: another address location)
jmp (pseudo code: starting loop address)

Lets explain how this works, the processor will keep executing instructions sequentially ... no matter what. So the moment it enters this loop it will add register bx to ax and store in ax, add register cx to ax and store to ax, cmp ax, dx (this means subtract dx from ax) the jz instruction means jump to (another address location) if the zero flag is set (which is a bit in the flag register that will be set if the result of the above subtraction is zero), then jmp to starting loop address (pretty straight forward) and redo the whole thing.

让我们解释一下这是如何工作的,处理器将继续按顺序执行指令……无论如何。所以当它进入这个循环时,它将寄存器 bx 添加到 ax 并存储在 ax 中,将寄存器 cx 添加到 ax 并存储到 ax、cmp ax、dx(这意味着从 ax 中减去 dx) jz 指令意味着跳转到(另一个地址location)如果设置了零标志(如果上述减法的结果为零,则标志寄存器中的一个位将被设置),然后跳转到起始循环地址(非常直接)并重做整个事情。

The reason I bothered you with all this assembly is to show you that this would translate in C to

我用所有这些程序集打扰你的原因是向你展示这将在 C 中转换为

int A,B,C,D;
// initialize to what ever;

while(true)
{
A = A + B;
A = A + C;

if((A-D)==0)
{break;}

}

// if((X-Y)==0){break;} is the 
// cmp ax, dx
// jz  (pseudo code: another address location)

So imagine the senario in assembly if you just had a very long list of instructions that didn't end with a jmp (the while loop) to repeat some section or load a new program or do something ... Eventually the processor will reach the last instruction and then load the following instruction to find nothing (it will then freeze or triple fault or something).

因此,想象一下汇编中的 senario,如果您有很长的指令列表,这些指令没有以 jmp(while 循环)结尾来重复某些部分或加载新程序或执行某些操作……最终处理器将到达最后一条指令,然后加载下面的指令,什么也没找到(然后它会冻结或三重故障或其他什么)。

That is exactly why, when you want the program to do nothing until an event is triggered, you have to use a while(1) loop, so that the processor keeps jumping in its place and not reach that empty instruction address. When the event is triggered, it jumps to the event handler instructions address, executes it, clears the interrupt and goes back to your while(1) loop just jumping in its place awaiting further interrupts. Btw the while(1) is called a superloop if you want to read more about it ... Just for whoever that is insanely itching to argue and comment negatively at this point, this is not an assembly tutorial or a lecture or anything. It's just plain English explanation that is as simple as possible, overlooking a lot of underlying details like pointers and stacks and whatnot and at some instance over simplifying things to get a point across. No one is looking for documentation accuracy over here and I know this C code won't compile like this, but this is only for Demo !!

这就是为什么,当您希望程序在事件触发之前什么都不做时,您必须使用 while(1) 循环,以便处理器保持原位跳转,而不是到达那个空指令地址。当事件被触发时,它跳转到事件处理程序指令地址,执行它,清除中断并返回到你的 while(1) 循环,只是在它的位置上跳转等待进一步的中断。顺便说一句,如果你想阅读更多关于 while(1) 的内容,它被称为超级循环......对于那些在这一点上疯狂地想要争论和负面评论的人来说,这不是汇编教程或讲座或任何东西。这只是简单的英文解释,尽可能简单,忽略了很多底层细节,比如指针和堆栈等等,在某些情况下,为了得到一个观点而过度简化事情。没有人在这里寻找文档的准确性,我知道这个 C 代码不会像这样编译,但这仅适用于 Demo !!

回答by David Hammen

This is tagged C, but I'll start with a C++ perspective. In C++11, the compiler is free to optimize while(1);away.

这被标记为 C,但我将从 C++ 的角度开始。在 C++11 中,编译器可以自由地优化while(1);掉。

From the C++11 draft standard n3092, section 6.5 paragraph 5 (emphasis mine):

来自 C++11 草案标准 n3092,第 6.5 节第 5 段(强调我的):

A loop that, outside of the for-init-statement in the case of a for statement,
— makes no calls to library I/O functions, and
— does not access or modify volatile objects, and
— performs no synchronization operations (1.10) or atomic operations (Clause 29)
may be assumed by the implementation to terminate. [Note: This is intended to allow compiler transformations, such as removal of empty loops, even when termination cannot be proven.— end note ]

在 for 语句的情况下,在 for-init 语句之外的循环
——不调用库 I/O 函数,并且
——不访问或修改易失性对象,并且
——不执行同步操作 (1.10)或原子操作(第 29 条)
可能由实现来终止。[注意:这旨在允许编译器转换,例如删除空循环,即使无法证明终止。— 尾注 ]


The C11 standard has a similar entry, but with one key difference. From the C11 draft standard n1570, (emphasis mine):


C11 标准有一个类似的条目,但有一个关键区别。从 C11 草案标准 n1570,(强调我的):

An iteration statement whose controlling expression is not a constant expression,156)that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)
156) An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.
157) This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven.

循环语句,其控制表达式不是一个常量表达式156)不执行任何输入/输出操作,不访问易失性的目的,并且不执行同步或在其主体的原子操作,控制表达,或(在一对的情况下语句)它的表达式 3,可以由实现假设终止。157)
156) 一个省略的控制表达式被一个非零常量替换,它是一个常量表达式。
157)这是为了允许编译器转换,例如即使在无法证明终止时也可以删除空循环。


This means while(1);can be assumed to terminate in C++11 but not in C11. Even with that, note 157 (not binding) is interpreted by some vendors as allowing them to remove that empty loop. The difference between while(1);in C++11 and C11 is that of defined versus undefined behavior. Because the loop is empty it can be deleted in C++11. In C11, while(1);is provably non-terminating, and that is undefined behavior. Since the programmer has invoked UB, the compiler is free to do anything, including deleting that offending loop.


这意味着while(1);可以假设在 C++11 中终止,但不在 C11 中终止。即便如此,一些供应商将注释 157(非绑定)解释为允许他们删除该空循环。while(1);C++11 和 C11之间的区别在于定义与未定义行为的区别。因为循环是空的,所以可以在 C++11 中删除它。在 C11 中,while(1);可证明是非终止的,这是未定义的行为。由于程序员调用了 UB,编译器可以自由地做任何事情,包括删除那个有问题的循环。

There have been a number of stackoverflow discussions on optimizing compilers deleting while(1);. For example, Are compilers allowed to eliminate infinite loops?, Will an empty for loop used as a sleep be optimized away?, Optimizing away a "while(1);" in C++0x. Note that the first two were C-specific.

关于优化编译器删除while(1);. 例如,是否允许编译器消除无限循环?,用作睡眠的空 for 循环会被优化掉吗?,优化掉一个 "while(1);" 在 C++0x 中。请注意,前两个是特定于 C 的。

回答by ouah

An usage on embedded software is to implement a software reset using the watchdog:

嵌入式软件的一个用法是使用看门狗实现软件复位:

while (1);

or equivalent but safer as it makes the intent more clear:

或等效但更安全,因为它使意图更加明确:

do { /* nothing, let's the dog bite */ } while (1);

If the watchdog is enabled and is not acknowledged after x milliseconds we know it will reset the processor so use this to implement a software reset.

如果看门狗被启用并且在 x 毫秒后未被确认,我们知道它将重置处理器,因此使用它来实现软件重置。

回答by Mahonri Moriancumer

I assume that the while(1);is not associated with a doloop...

我认为这while(1);do循环无关......

The only semi-useful implementation of while(1);I have seen is a do-nothing loop waiting for an interrupt; such as a parent process waiting for a SIGCHLD, indicating a child process has terminated. The parent's SIGCHLD handler, after all child processes have terminated, can terminate the parent thread.

while(1);我见过的唯一半有用的实现是等待中断的无操作循环;例如父进程在等待 SIGCHLD,表明子进程已终止。在所有子进程终止后,父线程的 SIGCHLD 处理程序可以终止父线程。

It does the trick, but wastes a lot of CPU-time. Such a usage should perhaps perform some sort of sleep to relinquish the processor periodically.

它可以解决问题,但会浪费大量 CPU 时间。这种用法也许应该执行某种睡眠以定期放弃处理器。

回答by waldol1

One place that I have seen a while(1);is in embedded programming.

我见过的一个地方while(1);是嵌入式编程。

The architecture used a main thread to monitor events and worker threads to handle them. There was a hardware watchdog timer (explanation here) that would perform a soft reset of the module after a period of time. Within the main thread polling loop, it would reset this timer. If the main thread detected an unrecoverable error, a while(1);would be used to tie up the main thread, thus triggering the watchdog reset. I believe that assert failure was implemented with a while(1);as well.

该架构使用主线程来监视事件和工作线程来处理它们。有一个硬件看门狗定时器(在这里解释),它会在一段时间后执行模块的软复位。在主线程轮询循环中,它将重置此计时器。如果主线程检测到不可恢复的错误,while(1);就会使用a来占用主线程,从而触发看门狗复位。我相信断言失败也是用 a 实现的while(1);

回答by Thomas Padron-McCarthy

As others have said, it's just an infinite loop that does nothing, completely analogous to

正如其他人所说,它只是一个什么都不做的无限循环,完全类似于

while (1) {
    /* Do nothing */
}

The loop with the semicolon does have a body. When used as a statement, a single semicolon is a null statement, and the loop body consists of that null statement.

带分号的循环确实有一个主体。当用作语句时,单个分号是空语句,循环体由该空语句组成。

For readability, to make it plain to the reader that the null statement is the body of the loop, I recommend writing it on a separate line:

为了可读性,为了让读者明白 null 语句是循环的主体,我建议将它写在单独的行上:

while (1)
    ;

Otherwise it is easy to miss it at the end of the "while" line, where there usually isn't a semicolon, and the reader can mistake the next line as the body of the loop.

否则很容易在“while”行的末尾错过它,那里通常没有分号,读者可能会将下一行误认为是循环体。

Or use an empty compound statement instead.

或者改用空的复合语句。

回答by ST3

This may be used to wait for Interrupt. Basically you initialize all things you need and start waiting for some thing to occur. After that some specific function is called and executed, after that it goes back to waiting state.

这可用于等待中断。基本上你初始化所有你需要的东西并开始等待一些事情发生。之后调用并执行某些特定函数,然后返回等待状态。

That thing could be button pressed, mouse click/move, data received and etc.

那个东西可能是按下按钮、鼠标点击/移动、接收到的数据等等。

What is more I would say, similarstuff is really often used by UI frameworks. While it waits for signals about user actions.

更重要的是,UI 框架确实经常使用类似的东西。当它等待有关用户操作的信号时。

回答by frogatto

In AVR chipsets programming (using C programming language) this statement is frequently used, It plays a role like event loop.

在 AVR 芯片组编程(使用 C 编程语言)中,经常使用该语句,它起到类似于事件循环的作用。

Suppose I want to design a count-up counter, So I can use this code for implementing it:

假设我想设计一个计数计数器,那么我可以使用以下代码来实现它:

void interrupt0() {
   /* check if key pressed, count up the counter */
}

void main() {
    /* Common inits */
    /* Enable interrupt capability and register its routine */

    /* Event loop */
    while(1);
} 

回答by Zach P

while(1);

is actually very useful. Especially when it's a program that has some sort of passcode or so and you want to disable the use of the program for the user because, for an example, he entered the wrong passcode for 3 times. Using a while(1);would stop the program's progress and nothing would happen until the program is rebooted, mostly for security reasons.

实际上非常有用。特别是当它是一个有某种密码的程序并且你想禁止用户使用该程序时,例如,他输入了 3 次错误的密码。使用 awhile(1);会停止程序的进程,并且在程序重新启动之前不会发生任何事情,主要是出于安全原因。