問題描述
無限循環有幾種可能,我會選擇以下幾種:
for(;;) {}
while(1) {}
/while(true) {}
do {} while(1)
/do {} while(true)
是否有某種形式應該選擇哪一種?現代編譯器是否對中間語句和最后一條語句有所區別,或者它是否意識到這是一個無限循環并完全跳過檢查部分?
正如前面提到的,我忘記了 goto
,但這樣做是因為我根本不喜歡它作為命令.
Edit2:我對從 kernel.org 獲取的最新版本做了一些 grep.隨著時間的推移,我似乎沒有太大變化(至少在內核中)
問這個問題的問題是你會得到很多主觀的答案,只是簡單地說明我更喜歡這個......".我不會做出這些毫無意義的陳述,而是嘗試用事實和參考資料來回答這個問題,而不是個人意見.
根據經驗,我們可以先排除 do-while 替代方案(和 goto),因為它們并不常用.我不記得在由專業人員編寫的實時生產代碼中看到過它們.
while(1)
、while(true)
和 for(;;)
是實際代碼中普遍存在的 3 個不同版本.它們當然是完全等價的,并產生相同的機器代碼.
for(;;)
這是永恒循環的原始規范示例.在 Kernighan 和 Ritchie 的古老 C 圣經C 編程語言中,我們可以讀到:
K&R 第二版 3.5:
for (;;) {...}
<塊引用>
是一個無限"循環,大概會被其他方式打破,例如作為休息或返回.使用 while 還是 for 在很大程度上是一個問題個人喜好.
很長一段時間(但不是永遠),這本書被視為經典和 C 語言的定義.由于 K&R 決定展示一個
for(;;)
的例子,至少在 1990 年 C 標準化之前,這被認為是最正確的形式.然而,K&R 自己已經表示這是一個偏好問題.
今天,K&R 是一個非常有問題的來源,用作規范的 C 參考.它不僅多次過時(不是針對 C99 或 C11),而且還宣揚在現代 C 編程中通常被認為是壞的或公然危險的編程實踐.
盡管 K&R 是一個可疑的來源,但這一歷史方面似乎是支持
for(;;)
的最有力論據.反對
for(;;)
循環的論點是它有點晦澀難懂.要了解代碼的作用,您必須了解標準中的以下規則:ISO 9899:2011 6.8.5.3:
for ( clause-1 ; expression-2 ; expression-3 ) 語句
/--/
<塊引用>子句 1 和表達式 3 都可以省略.省略的表達式-2由一個非零常數代替.
根據標準中的這段文字,我認為大多數人會同意它不僅晦澀難懂,而且很微妙,因為 for 循環的第一和第三部分在省略時的處理方式與第二部分不同.
while(1)
這應該是比
for(;;)
更易讀的形式.然而,它依賴于另一個晦澀但眾所周知的規則,即 C 將所有非零表達式視為布爾邏輯真.每個 C 程序員都知道這一點,所以這不是什么大問題.這種形式有一個很大的實際問題,即編譯器往往會給出警告:條件總是為真"或類似的.這是一個很好的警告,您真的不想禁用它,因為它對于查找各種錯誤很有用.例如,當程序員打算編寫
while(i == 1)
時,會出現諸如while(i = 1)
之類的錯誤.此外,外部靜態代碼分析器可能會抱怨條件始終為真".
while(true)
為了使
while(1)
更具可讀性,有些使用while(true)
代替.程序員之間的共識似乎是這是最易讀的形式.然而,這種形式與
while(1)
有同樣的問題,如上所述:condition is always true"警告.對于 C,這種形式還有另一個缺點,即它使用了 stdbool.h 中的宏
true
.所以為了進行這個編譯,我們需要包含一個頭文件,這可能不方便.在 C++ 中,這不是問題,因為bool
作為原始數據類型存在,而true
是語言關鍵字.這種形式的另一個缺點是它使用 C99 bool 類型,該類型僅在現代編譯器上可用且不向后兼容.同樣,這只是 C 中的問題,而不是 C++ 中的問題.
那么使用哪種形式?兩者似乎都不完美.正如 K&R 在黑暗時代已經說過的那樣,這是個人喜好問題.
就個人而言,我總是使用 for(;;)
只是為了避免其他形式經常生成的編譯器/分析器警告.但也許更重要的是因為這個:
如果連 C 初學者都知道 for(;;)
意味著一個永恒的循環,那么你想讓誰的代碼更易讀?
我想這就是真正歸結起來的原因.如果您發現自己試圖讓您的源代碼對于那些甚至不了解編程語言的基本部分的非程序員來說是可讀的,那么您只是在浪費時間.他們不應該閱讀您的代碼.
而且由于每個應該閱讀你的代碼的人都已經知道 for(;;)
的意思,所以沒有必要讓它進一步可讀 - 它已經是可讀.
There are several possibilities to do an endless loop, here are a few I would choose:
for(;;) {}
while(1) {}
/while(true) {}
do {} while(1)
/do {} while(true)
Is there a certain form which one should choose? And do modern compilers make a difference between the middle and the last statement or does it realize that it is an endless loop and skips the checking part entirely?
Edit: as it has been mentioned I forgot goto
, but this was done out of the reason that I don't like it as a command at all.
Edit2: I made some grep on the latest versions taken from kernel.org. I does seems as nothing much changed over time (within the Kernel at least)
The problem with asking this question is that you'll get so many subjective answers that simply state "I prefer this...". Instead of making such pointless statements, I'll try to answer this question with facts and references, rather than personal opinions.
Through experience, we can probably start by excluding the do-while alternatives (and the goto), as they are not commonly used. I can't recall ever seeing them in live production code, written by professionals.
The while(1)
, while(true)
and for(;;)
are the 3 different versions commonly existing in real code. They are of course completely equivalent and results in the same machine code.
for(;;)
This is the original, canonical example of an eternal loop. In the ancient C bible The C Programming Language by Kernighan and Ritchie, we can read that:
K&R 2nd ed 3.5:
for (;;) { ... }
is an "infinite" loop, presumably to be broken by other means, such as a break or return. Whether to use while or for is largely a matter of personal preference.
For a long while (but not forever), this book was regarded as canon and the very definition of the C language. Since K&R decided to show an example of
for(;;)
, this would have been regarded as the most correct form at least up until the C standardization in 1990.However, K&R themselves already stated that it was a matter of preference.
And today, K&R is a very questionable source to use as a canonical C reference. Not only is it outdated several times over (not addressing C99 nor C11), it also preaches programming practices that are often regarded as bad or blatantly dangerous in modern C programming.
But despite K&R being a questionable source, this historical aspect seems to be the strongest argument in favour of the
for(;;)
.The argument against the
for(;;)
loop is that it is somewhat obscure and unreadable. To understand what the code does, you must know the following rule from the standard:ISO 9899:2011 6.8.5.3:
for ( clause-1 ; expression-2 ; expression-3 ) statement
/--/
Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
Based on this text from the standard, I think most will agree that it is not only obscure, it is subtle as well, since the 1st and 3rd part of the for loop are treated differently than the 2nd, when omitted.
while(1)
This is supposedly a more readable form than
for(;;)
. However, it relies on another obscure, although well-known rule, namely that C treats all non-zero expressions as boolean logical true. Every C programmer is aware of that, so it is not likely a big issue.There is one big, practical problem with this form, namely that compilers tend to give a warning for it: "condition is always true" or similar. That is a good warning, of a kind which you really don't want to disable, because it is useful for finding various bugs. For example a bug such as
while(i = 1)
, when the programmer intended to writewhile(i == 1)
.Also, external static code analysers are likely to whine about "condition is always true".
while(true)
To make
while(1)
even more readable, some usewhile(true)
instead. The consensus among programmers seem to be that this is the most readable form.However, this form has the same problem as
while(1)
, as described above: "condition is always true" warnings.When it comes to C, this form has another disadvantage, namely that it uses the macro
true
from stdbool.h. So in order to make this compile, we need to include a header file, which may or may not be inconvenient. In C++ this isn't an issue, sincebool
exists as a primitive data type andtrue
is a language keyword.Yet another disadvantage of this form is that it uses the C99 bool type, which is only available on modern compilers and not backwards compatible. Again, this is only an issue in C and not in C++.
So which form to use? Neither seems perfect. It is, as K&R already said back in the dark ages, a matter of personal preference.
Personally, I always use for(;;)
just to avoid the compiler/analyser warnings frequently generated by the other forms. But perhaps more importantly because of this:
If even a C beginner knows that for(;;)
means an eternal loop, then who are you trying to make the code more readable for?
I guess that's what it all really boils down to. If you find yourself trying to make your source code readable for non-programmers, who don't even know the fundamental parts of the programming language, then you are only wasting time. They should not be reading your code.
And since everyone who should be reading your code already knows what for(;;)
means, there is no point in making it further readable - it is already as readable as it gets.
這篇關于C/C++ 中的無限循環的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!