use*_*519 12 c c++ for-loop comma-operator
我遇到了一个代码如下的for循环:
for ( argc--, argv++; argc > 0; argc--, argv++ )
Run Code Online (Sandbox Code Playgroud)
它是如何工作的?通常for循环看起来像这样:
for (initialization; condition; increment) {/*body of the loop*/}
Run Code Online (Sandbox Code Playgroud)
但是这不包含任何逗号 - 逗号的含义是什么?
Vla*_*cow 26
在C标准(6.8.5.3 for语句)中,for语句以下列形式表示
for ( clause-1 ; expression-2 ; expression-3 ) statement
Run Code Online (Sandbox Code Playgroud)
根据第1条,有书面说明
如果clause-1是表达式,则在第一次控制表达式求值之前将其计算为void表达式
在这个for语句中
for ( argc--, argv++; argc > 0; argc--, argv++ )
Run Code Online (Sandbox Code Playgroud)
clause-1是argc--, argv++基于逗号运算符的表达式.来自C标准(6.5.17逗号运算符)
2逗号运算符的左操作数被计算为void表达式; 它的评估与右操作数之间存在一个序列点.然后评估右操作数; 结果有它的类型和价值.
唯一的特点是运算符的结果不用于for语句.该表达用于其副作用.
通常,传递给正在运行的程序的第一个参数是它的名称.第1节中的表达式跳过了第一个参数.
比较这两个程序的输出.我们假设用户指定了命令行参数
first second third
Run Code Online (Sandbox Code Playgroud)
该程序的程序输出
#include <stdio.h>
int main( int argc, char * argv[] )
{
for ( argc--, argv++; argc > 0; argc--, argv++ )
{
puts( *argv );
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是
first
second
third
Run Code Online (Sandbox Code Playgroud)
当子句-1为空(既不是表达式也不是声明)时,该程序的程序输出
#include <stdio.h>
int main( int argc, char * argv[] )
{
for ( /*argc--, argv++*/; argc > 0; argc--, argv++ )
{
puts( *argv );
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是
./prog.exe
first
second
third
Run Code Online (Sandbox Code Playgroud)
为了使逗号运算符清晰,可以将程序视为第一个演示程序,而不是for循环使用while循环.
#include <stdio.h>
int main( int argc, char * argv[] )
{
while ( argv++, --argc > 0 )
{
puts( *argv );
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出将与第一个示范程序中的输出相同
first
second
third
Run Code Online (Sandbox Code Playgroud)
这里是while语句,也使用了逗号运算符.区别在于,在这种情况下,逗号运算符的值用作条件的值.
注意表达式-3本身也用逗号运算符表示一个表达式.
此外,当问题用C++标记标记时,您应该知道在C++中,for语句的第二个子句(在C++中它被命名为condition)也可以是表达式或声明.
小智 8
正如许多答案中所述,这是逗号运算符,所以
argc--, argv++
Run Code Online (Sandbox Code Playgroud)
只是一个表达.
逗号运算符评估两侧,先左,然后右.结果是右侧的结果.所以你可以写一些奇怪的东西,比如
int a = (x += 5, x + 2);
Run Code Online (Sandbox Code Playgroud)
这将分配结果前加5至x x + 2到a.这样的代码令人困惑,应该避免.但它演示了逗号运算符的一个重要属性:
它充当一个序列点:使用上面的代码,您可以保证在评估之前已经将5添加到x(x的值确实已更改)x + 2.
逗号运算符的主要合理用法是您的问题中显示的用法.它可以在更复杂的for循环中使用,例如具有多种副作用和有保证的顺序.
为了澄清为什么测序可能很重要(它不在你的例子中,因为副作用不相互依赖),请看这个(人为的)例子:
int i, j;
for (i = j = 0; i < 10; ++i, j+=i)
{
printf("%d\n", j);
}
Run Code Online (Sandbox Code Playgroud)
如果逗号运算符未在此处引入序列点,则您将不知道是j+=i添加递增的i还是不递增的序列点.
在此for循环中,第一个和最后一个表达式中使用了逗号运算符。所以for声明就像
for(
(argc--, argv++); // Expression 1
argc > 0; // Expression 2
(argc--, argv++) // Expression 3
)
Run Code Online (Sandbox Code Playgroud)
只有三个表达式(argc--, argv++), argc > 0并且(argc--, argv++)。
表达式1不一定是声明语句,它可以是任何有效的表达式,甚至可以省略
for(;expression2; expression3)
Run Code Online (Sandbox Code Playgroud)
或者所有表达式都可以省略
for(;;)
Run Code Online (Sandbox Code Playgroud)
在给定的 for 循环中,(argc--, argv++)用作更新变量的第一个表达式argc,并且argv(argc将减 1,指针argv将加 1)。一旦这些变量的副作用完成,程序将在检查argc > 0for后进入循环体true。这就是当你这样做时会发生的事情
for( i = 1; i < 10; i++)
Run Code Online (Sandbox Code Playgroud)
i = 1更新i为1,然后检查条件。的更新i仅完成一次,然后由表达式更新其余部分i++。