如何在C ++'for'循环中放置两个递增语句?

时间:2009-08-05 09:40:43

标签: c++ for-loop comma-operator

我想在for - 循环条件中增加两个变量,而不是一个。

类似于:

for (int i = 0; i != 5; ++i and ++j) 
    do_something(i, j);

这是什么语法?

8 个答案:

答案 0 :(得分:136)

一个常见的习惯用法是使用comma operator来计算两个操作数,并返回第二个操作数。因此:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

但它真的是一个逗号运算符吗?

现在已经写过,一位评论者认为它实际上是for语句中的一些特殊的语法糖,而不是逗号运算符。我在GCC检查了如下:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

我期待x拿起a的原始值,所以它应该显示为5,6,7 ..对于x。我得到的是这个

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

但是,如果我将表达式放在括号中以强制解析器真正看到逗号运算符,我就会得到这个

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

最初我认为这表明它根本不是一个逗号运算符,但事实证明,这只是一个优先问题 - 逗号运算符有lowest possible precedence,所以表达式x = i ++,a ++被有效地解析为(x = i ++),a ++

感谢所有评论,这是一次有趣的学习经历,我已经使用C多年了!

答案 1 :(得分:53)

试试这个

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

答案 2 :(得分:5)

尽量不要这样做!

来自http://www.research.att.com/~bs/JSF-AV-rules.pdf

   AV规则199
  for循环中的增量表达式除了更改单个循环外不会执行任何操作   循环参数到循环的下一个值。

     

理由:可读性。

答案 3 :(得分:3)

for (int i = 0; i != 5; ++i, ++j) 
    do_something(i, j);

答案 4 :(得分:2)

我来到这里是为了提醒自己如何将第二个索引编码到FOR循环的increment子句中,我知道这可以主要通过在我合并到另一个项目中的示例中观察它来完成,该项目是用C ++编写的。 / p>

今天,我在C#工作,但我确信它在这方面会遵守相同的规则,因为FOR语句是所有编程中最古老的控制结构之一。值得庆幸的是,我最近花了好几天精确记录了我的一个旧C程序中FOR循环的行为,我很快意识到这些研究的课程适用于当今的C#问题,特别是对于第二个索引变量。

对于粗心的人,以下是我的观察摘要。通过仔细观察Locals窗口中的变量,我今天看到的所有事情都证实了我的期望,即C#FOR语句的行为与C或C ++ FOR语句完全相同。

  1. 第一次执行FOR循环时,会跳过increment子句(三个中的第3个)。在Visual C和C ++中,增量生成为实现循环的块中间的三个机器指令,因此初始传递仅运行初始化代码一次,然后跳过增量块以执行终止测试。这实现了FOR循环执行零次或多次的功能,具体取决于其索引和限制变量的状态。
  2. 如果循环体执行,则它的最后一个语句是跳转到第一次迭代跳过的三个增量指令中的第一个。执行完这些后,控制自然会落入实现中间子句的极限测试代码中。该测试的结果确定FOR循环的主体是否执行,或者控制是否转移到其范围底部的跳转之后的下一条指令。
  3. 由于控制从FOR循环块的底部传输到增量块,因此索引变量在执行测试之前递增。这种行为不仅解释了为什么必须按照学习方式编写限制子句的代码,而且它会影响您通过逗号运算符添加的任何辅助增量,因为它成为第三个子句的一部分。因此,它在第一次迭代时没有改变,但它在最后一次迭代中,它从不执行主体。
  4. 如果您的索引变量中的任何一个在循环结束时仍保留在作用域中,则在真正的索引变量的情况下,它们的值将高于停止循环的阈值。同样,例如,如果第二个变量在输入循环之前被初始化为零,那么它在结尾处的值将是迭代计数,假设它是一个增量(++),而不是一个减量,并且没有任何内容循环体改变了它的价值。

答案 5 :(得分:1)

我同意squelart。增加两个变量是容易出错的,特别是如果你只测试其中一个变量。

这是可读的方式:

for(int i = 0; i < 5; ++i) {
    ++j;
    do_something(i, j);
}

For循环适用于循环在一个递增/递减变量上运行的情况。对于任何其他变量,请在循环中更改它。

如果您需要ji绑定,为什么不保留原始变量并添加i

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

如果你的逻辑更复杂(例如,你需要实际监控多个变量),我会使用while循环。

答案 6 :(得分:0)

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

答案 7 :(得分:0)

使用数学。如果这两个操作在数学上依赖于循环迭代,为什么不进行数学运算?

int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
    do_something (counter+i, counter+j);

或者,更具体地说是OP的例子:

for(int i = 0; i != 5; ++i)
    do_something(i, j+i);

特别是如果你按价值传递给一个函数,那么你应该得到一些完全符合你想要的东西。