繁体   English   中英

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

[英]How do I put two increment statements in a C++ 'for' loop?

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

所以像:

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

这是什么语法?

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

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 的原始值,所以它应该为 x 显示 5,6,7..。 我得到的是这个

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

最初我认为这表明它根本不像逗号运算符,但事实证明,这只是一个优先级问题 - 逗号运算符的优先级最低,因此表达式 x=i++,a++ 是有效的解析为 (x=i++),a++

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

试试这个

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

尽量不要这样做!

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

反病毒规则 199
除了将单个循环参数更改为循环的下一个值之外,for 循环中的增量表达式不会执行任何操作。

基本原理:可读性。

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

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

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

对于粗心的人,以下是我的观察摘要。 通过仔细观察 Locals 窗口中的变量,我今天看到的一切证实了我的预期,即 C# FOR 语句的行为与 C 或 C++ FOR 语句完全一样。

  1. FOR 循环第一次执行时,会跳过 increment 子句(三个子句中的第三个)。 在 Visual C 和 C++ 中,增量作为三个机器指令生成在实现循环的块中间,因此初始 pass 只运行一次初始化代码,然后跳过增量块执行终止测试。 这实现了 FOR 循环执行零次或多次的功能,具体取决于其索引和限制变量的状态。
  2. 如果循环体执行,它的最后一条语句是跳转到第一次迭代跳过的三个增量指令中的第一个。 这些执行后,控制自然落入实现中间子句的极限测试代码。 该测试的结果决定了 FOR 循环体是否执行,或者控制是否转移到下一条指令,越过其作用域底部的跳转。
  3. 由于控制从 FOR 循环块的底部转移到增量块,索引变量在执行测试之前被增加。 这种行为不仅解释了为什么您必须按照您所学的方式对限制子句进行编码,而且它会影响您通过逗号运算符添加的任何二级增量,因为它成为第三个子句的一部分。 因此,它在第一次迭代时没有改变,但在最后一次迭代时发生了变化,它从不执行主体。

如果您的任一索引变量在循环结束时仍在作用域内,则在真正的索引变量的情况下,它们的值将比停止循环的阈值高一个。 同样,例如,如果在进入循环之前将第二个变量初始化为零,则其最后的值将是迭代计数,假设它是增量 (++),而不是减量,并且循环体改变它的值。

我同意尖叫。 增加两个变量很容易出错,尤其是当您只测试其中一个时。

这是执行此操作的可读方式:

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM