有几种方法可以实现无止境的循环,我会 Select 以下几种:

  • for(;;) {}
  • while(1) {}/while(true) {}
  • do {} while(1)/do {} while(true)

是否有某种形式可以 Select ?现代的编译器会在中间语句和最后语句之间产生差异吗?还是会意识到这是一个无休止的循环,会完全跳过判断部分?

编辑:正如前面提到的,我忘记了goto,但这样做是因为我根本不喜欢它作为命令.

Edit2:我对内核中的最新版本做了一些修改.组织.随着时间的推移,我似乎没有什么变化(至少在内核内部)

推荐答案

问这个问题的问题是,你会得到如此多的主观答案,只是简单地说"我更喜欢这个……".与其说这些毫无意义的话,我会试着用事实和参考资料来回答这个问题,而不是个人观点.

根据经验,我们可能可以从排除do-while选项(和goto)开始,因为它们并不常用.我不记得在专业人士编写的实时生产代码中见过它们.

while(1)while(true)for(;;)是真实代码中常见的三个不同版本.当然,它们是完全等价的,并产生相同的机器代码.


100

  • 这是一个永恒循环的原始的、规范的例子.在Kernighan和Ritchie的古代C圣经The C Programming Language中,我们可以读到:

    K&;R第二版3.5:

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

    /--/

    子句-1和表达式-3都可以省略.省略的表达式-2 替换为非零常量.

    基于标准中的这一文本,我想大多数人都会同意,它不仅晦涩难懂,而且很微妙,因为当省略for循环的第一部分和第三部分时,其处理方式与第二部分不同.


100

  • 这应该是一种比for(;;)更可读的形式.然而,它依赖于另一条模糊但众所周知的规则,即C将所有非零表达式视为布尔逻辑true.每个C程序员都知道这一点,所以这不太可能是个大问题.

  • 这种形式有一个很大的实际问题,即编译器倾向于给它一个警告:"条件始终为真"或类似的警告.这是一个很好的警告,是一种你真的不想禁用的警告,因为它对查找各种错误很有用.例如一个bug,比如while(i = 1),当程序员打算写while(i == 1)时.

    此外,外部静态代码分析器可能会抱怨"条件总是正确的".


100

  • 为了让while(1)更具可读性,有些人使用while(true).程序员之间的共识似乎是,这是最具可读性的形式.

  • 但是,此表单与while(1)有相同的问题,如上所述:"条件始终为真"警告.

  • 说到C,这种形式还有另一个缺点,即它使用stdbool中的宏true.h、 因此,为了进行编译,我们需要包含一个头文件,这可能不方便,也可能不方便.在C++中,这不是问题,因为bool作为原始数据类型存在,true是语言关键字.

  • 这种形式的另一个缺点是它使用C99布尔类型,该类型仅在现代编译器上可用,不能向后兼容.同样,这只是C中的问题,而不是C++中的问题.


那么应该使用哪种形式呢?两者似乎都不完美.正如K&;R在黑暗时代已经说过的那样,这是个人喜好的问题.

就我个人而言,我总是使用for(;;)只是为了避免其他表单经常生成的编译器/分析器警告.但也许更重要的是因为:

If even a C beginner knows that 100 means an eternal loop, then who are you trying to make the code more readable for?

我想这就是这一切真正归结起来的原因.如果您发现自己试图使您的源代码可读,而非程序员甚至不了解编程语言的基本部分,那么您只是在浪费时间.他们不应该读取您的代码.

而且,因 for each 正在阅读你的代码的人都已经知道for(;;)的意思,所以没有必要让它更具可读性——它已经是尽可能地可读了.

C++相关问答推荐

奇怪的print在getchar和getchar跳过后不工作

位屏蔽对于无符号转换是强制的吗?

通过管道将一个子系统的标准输出发送到另一个子系统的标准输出

在C中使用动态内存分配找到最小的负数

如何设置指针指向在函数中初始化的复合文字中的整数?

正在try 将文件/文件夹名从目录 struct 存储到链接列表

无效指针值在函数调用之间莫名其妙地改变

在传统操作系统上可以在虚拟0x0写入吗?

在c++中使用堆栈的有效括号

在C++中通过空指针隐式访问常量变量的值

如何在C中使printf不刷新标准输出?

如何在下面的C代码中正确管理内存?

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

为什么电路板被循环删除?

当我用scanf(&Q;%S%S%S&Q;,单词0,单词1,单词2)输入多个单词时,除了最后一个单词外,每个单词的第一个字符都丢失了

合并对 struct 数组进行排序

不带Malloc的链表

为什么argc和argv即使在主函数之外也能工作?

模仿 memmove 的行为

为什么创建局部变量的指针需要过程在堆栈上分配空间?