“;”的目的是什么?在for循环的末尾?


76

我发现以下代码:

int func_prim (int zahl) {
    int count;
    if (zahl < 0)
        return -1;

    for (count = 2; zahl % count != 0 && zahl >= count; count++);
    if (count == zahl)
        return 1;
    return 0;
}

功能的重点是检查数字是否是质数。

我不明白为什么循环;末尾会出现:

                                                            v
for (count = 2; zahl % count != 0 && zahl >= count; count++);

否则,代码将无法正常工作。

有什么解释?


48
因为作者是EVIL,所以for循环的末尾带有分号!在这种情况下,它应该自行运行。
sh1

21
@ sh1或者,如果作者希望将整个循环放在一行上,则{ }可以用来代替;该文件,以表明循环是有意的,它是空的,不包含任何后续行。
伊莱亚·卡根

22
@EliahKagan,有时当我感觉要强调要编写的循环主体的空虚时for (...) continue;
sh1

8
@coredump但是以这种方式使用分号的两个问题是(1)看起来像是一个错误,有些好心的开发人员可能会删除一天;(2)如果您看不到它,则可以期望它下面的语句是“循环的”语句。后者是一种特殊的危险,因为程序员学会了不要在行的末尾特别注意分号;因此,请注意。正如阅读的人往往不会注意到句子是否以句号结尾而不是结束一样
Dawood ibn Kareem 2015年

6
@ Marco13为什么会自动假定原始作者是无知的?您非常讨厌这种写作。但是您会发现很多人更喜欢for循环方法:毕竟,有一个初始化,一个停止条件和一个迭代,这些自然由for构造表达。您不同意,但是我相信作者知道什么是while循环。顺便说一句,这就是为什么您需要团队中的编码约定。
coredump

Answers:


89

它的含义与以下内容完全相同:

for(count = 2; zahl % count != 0 && zahl >= count; count++)
{
}

7
这是编写空循环主体的更好的方法(尽管{}在一行上书写可能是从视觉上更容易理解空主体的线索)。如果不是用于遗留代码,那么如果没有;空语句规则,该语言会更好。在;那之后是强制性do ... while(...)是愚蠢的为好,但至少我已经看到了一些巧妙的利用它。
马克·范·吕文

5
@MarcvanLeeuwen我发现它;更具可读性。空的块看起来像是个意外,就像程序员只是忘记填写主体一样。空洞的陈述清楚表明了他的意图。
Paul

19
@Paulpro,我发现这两个都是潜在的错误,并且for (...) { /* empty block */ }要比这两个都更清楚,以表明这是故意的。
atk 2015年

2
我不是C程序员,但是为什么这样做会有用呢?
伊森·比莱恩

6
@EthanBierlein的“工作”是由( );中的语句完成的;这个循环的重点是要count根据zahl
MM

53

for循环具有for关键字,其后是包含用分号分隔的三个可选表达式的括号,其后是在循环的每次迭代中执行的主体。

您的示例中for循环的目标是设置的值count,该值将与后面zahl的if语句进行比较。这是用分号分隔的表达式实现的,因此循环体不需要执行任何操作。

由于循环不需要执行任何操作,因此它使用空语句作为其主体。

如果;省略了末尾的for并且没有进行其他更改,则for循环之后的if语句本身将成为for循环的主体。(正如您所观察到的那样,这不是故意的,并且会破坏程序。)

但是,使一个循环体由;同一行中的单个循环组成不是写空循环体的唯一方法,也不是最明智的方法。它工作得很好,但问题是其他读者(也许是同一位程序员,稍后再返回该项目)可能想知道这是否真的是一个错误。毕竟,当使用C风格的语言进行编码时,经常在行尾键入分号,因此很容易在不属于它的地方键入多余的分号。

另一个问题是,在代码中有一个线环;作为其机身所选择的风格,也很难认出时,有人居然已经作出把一个的错误;时,一个不属于。

因此,这些替代方法可能是更可取的:

  • ;缩进的内容放在下一行上-如sh1所示
  • 将循环体写为空块{ },而不是空语句
  • 使循环主体成为一条continue;语句,这只会使循环继续进行下一次迭代(这与循环主体为空时发生的情况相同)-就像sh1所暗示的那样

4
虽然我可以同意;{},但我会发现这continue;很奇怪。在我看来,好像有人期望continue外循环之类。绝对是WTF时刻,您想要在代码中避免这些。我想{}以最易读的方式捕捉意图。
Angew不再为2015年

5
另一个选项(可以与其他选项组合使用)是插入注释:for (...) /* do nothing */ ;,以表明它是故意的。

2
我将添加其他选择来增加循环内的变量,例如:for(count=2; zahl % count != 0 && zahl >= count;) ++count;
Massa 2015年

3
@Massa-for根据定义,循环是一个计数的循环;出口增量器圈外让你没有理由使用forVSwhile任何责任。

@vaxquis你仍然有初始化;我本来应该int count = 2; while( zahl % count && zahl >= count ) ++count;从开头开始:D
Massa 2015年

41

for循环末尾的分号表示它没有主体。没有这种分号,C会认为该if语句是for循环的主体。


4
+ int(PI / 3)引起关注,而无需进行“是好的还是不好的编码实践”辩论。

明确地+1,这是一个干净,简短的事实答案,不会尝试将代码声明为糟糕的样式。

1
for循环肯定有一个主体。只是主体仅由null语句组成;。孤行;实际上在所有允许使用语句的地方都是有效的(如果不是实际上),因为孤行;是一个空语句(即一条语句)。
用户

22

for循环(迭代语句)的语法为

for ( clause-1 ; expression-2 ; expression-3 ) statement 

statement可以为空语句;)。C11 6.8.3说

空语句(仅由分号组成)不执行任何操作。

在第5段中,给出了一个示例

在程序片段中

char *s;
/* ... */
while (*s++ != '\0')
    ;

空语句用于向迭代语句提供空循环主体

同样的事情正在发生

for (count = 2; zahl % count != 0 && zahl >= count; count++);

;用于为for语句提供空循环主体。如果没有;该语句,则该for循环旁将被视为其主体并将被执行。


1
+ int(PI / 3)引起关注,而无需进行“是好的还是不好的编码实践”辩论。

@vaxquis; 是的,因为问题在于“为什么循环;最终要结束?” 。它不是关于“这是否是一种好习惯?”
haccks

17

除了已经说过的其他出色答案外,我想指出的是

for(count=2; zahl % count != 0 && zahl >= count; count++);

(即,for带有空语句的循环用于递增“计数器”)等效于

count=2;
while(zahl % count != 0  && zahl >= count)
{
    count++;
}

这将使代码的目标甚至比列出的替代方法更明确:如果不存在注释,如在当前情况下那样,带有空语句的循环可能会使必须维护或使用代码的另一个程序员感到困惑(就像以前那样)。 OP的情况)。

上下文可能有助于辨别语句的真实范围,但是在for具有空语句的while循环和具有语句的循环之间,后者需要较少的工作来了解其范围。


1
次要nitpick:这不是严格等效的,因为在第二个版本count中声明了更大的范围。
coredump

我的意思是,一般而言...count在这两个版本的函数开头都声明了这里。
coredump

2
@coredump:考虑到此循环的目的(在这种情况下)是为了获取count正确的值,以便可以进一步使用它,count它必须存在于较大的范围内才能完全起作用,并且因此,它是完全等效的。(尽管这仍然是对for循环的丑陋滥用,但Federico是对的,这是表达所涉及语义的正确方法。)
Mason Wheeler

@MasonWheeler是的,我正在考虑一般情况。两者在这里确实相等。
coredump

1
为什么for循环不清楚?我了解到for循环明确地在逻辑上将初始化,条件和迭代语句捆绑在一起。从来没有必要使用for循环,但是这种情况似乎是明智的并且编写得很干净。

12

;for循环仅仅意味着for循环不会做任何超过增加计数器count


12

for声明

for语句是一个循环语句,其结构允许简单的变量初始化,表达式测试和变量修改。进行计数器控制的循环非常方便。这是for语句的一般形式:

 for (initialize; test; step)
   statement

[...]

空声明

空语句只是单独一个分号。

 ;

空语句不执行任何操作。它不会在任何地方存储值。它不会在程序执行过程中花费时间。

通常,空语句用作循环语句的主体,或用作for语句中的一个或多个表达式。这是一个for语句的示例,该语句使用null语句作为循环的主体(并且还计算n的整数平方根,只是为了好玩):

 for (i = 1; i*i < n; i++)
   ;

这是另一个使用null语句作为for循环的主体并产生输出的示例:

 for (x = 1; x <= 5; printf ("x is now %d\n", x), x++)
   ;

有时也使用null语句来跟随标签,否则标签将成为块中的最后一件事。


在你的情况下,;空语句中的for声明

int func_prim (int zahl) {
  int count;
  if (zahl < 0)
    return -1;

  for (count = 2; zahl % count != 0 && zahl >= count; count++)
    ;
  if (count == zahl)
    return 1;
  return 0;
}

没有它,theif成为for语句:

int func_prim (int zahl) {
  int count;
  if (zahl < 0)
    return -1;

  for (count = 2; zahl % count != 0 && zahl >= count; count++)
    if (count == zahl)
      return 1;
  return 0;
}

因此,行为有所不同。


1
很好地引用了文档。+1


9

一个for循环将(通常)具有主体,

身体用括号括起来的地方 { }

但是,对于单个语句主体,花括号是可选的。

; 是一个空语句。

结合以上内容,很明显for循环执行到条件变为为止false


6

for循环基本上是遍历所有小于或等于zahl但大于2的数字并将其存储在变量中count。当它遍历所有这些数字时,它正在检查是否可以zahl被整除count。如果zahl被整除count,则循环停止。否则,当countequals时,循环将停止zahl

for循环后的if语句检查是否count等于zahl。如果是的话,那必须意味着循环遍历了所有小于zahl和大于2的数字。这意味着它zahl可以被所有小于其自身和大于2的数字整除,这就是zahl质数。


0

它指示for循环用于的语句。不能为空。至少它应该包含一个语句。; 是为迭代完成的空语句。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.