在C和C ++中使用逗号而不是分号的效果

我曾多次注意到,在重构各种C和C ++代码时,使用了逗号而不是分号来分隔语句。 像这样的东西;

int a = 0, b = 0; a = 5, b = 5; 

我会在哪里预期的

 int a = 0, b = 0; a = 5; b = 5; 

我知道C和C ++允许使用逗号来分隔语句(特别是循环标题),但是这两段代码之间有什么区别呢? 我的猜测是这个逗号已经被剪切和粘贴了,但这是一个错误,是否会影响执行?

这对您发布的代码没有任何影响。 一般来说,逗号分隔expression式就像分号一样,但是,如果将整个expression式作为expression式使用,则逗号运算符意味着expression式将计算为最后一个参数。

这是一个例子:

 b = (3,5); 

将评估3,然后5,并将后者分配给b。 所以b == 5。 请注意括号在这里很重要:

 b = 3, 5; 

将评估b = 3,然后5和整个expression式的结果是5,但是b == 3。

当您的迭代器代码不是简单的i ++时,逗号运算符在for循环中特别有用,但是您需要执行多个命令。 在这种情况下,分号与for循环语法无法正常工作。

逗号是一个运算符,它返回一个总是第二个(右)参数的值,而分号只是结束语句。 这允许逗号操作符在其他语句中使用,或者连接多个语句以显示为一个。

这里函数f(x)被调用,然后x > y被评估为if语句。

 if( y = f(x), x > y ) 

一个例子,它只是为了避免需要阻止

 if( ... ) x = 2, y = 3; if( ... ) { x = 2; y = 3; } 

逗号运算符从左到右评估所有操作数,结果是最后一个操作数的值。

如果要在“增量”部分执行多个操作,则它在for循环中最为有用,例如(反转string)

 for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper) std::swap(s[lower], s[upper]); 

另一个例子,它可能是一个选项(查找string中的所有事件):

 #include <string> #include <iostream> int main() { std::string s("abracadabra"); size_t search_position = 0; size_t position = 0; while (position = s.find('a', search_position), position != std::string::npos) { std::cout << position << '\n'; search_position = position + 1; } } 

特别是逻辑的不能用于这个条件,因为零和非零都可以表示在string中find字符。 另一方面,使用逗号,每当条件被评估时调用position = s.find() ,但是这部分条件的结果被忽略。

当然,还有其他的方式来编写循环:

 while ((position = s.find('a', search_position)) != std::string::npos) 

要不就

 while (true) { position = s.find('a', search_position); if (position == std::string::npos) break; ... } 

一个用法是在代码打高尔夫球:

 if(x==1)y=2,z=3; if(x==1){y=2;z=3;} 

第一行比较短,但是在正常的开发中看起来太混乱了

正如弗兰克所说 ,在你的例子中如何使用逗号运算符不会导致错误。 逗号操作符可能会让人困惑,原因如下:

  • 它并不经常被看到,因为这只是在一些特殊情况下才需要的
  • 还有其他一些可能看起来像逗号运算符的语法用法 – 但它们不是(逗号用于分隔函数参数/参数,用逗号分隔variables声明或初始化符)

由于它很混乱,而且往往是不必要的,所以除了一些非常特殊的情况之外,应该避免逗号操作符:

  • for语句的一个或多个控制expression式中执行多个操作可能很有用
  • 它可以在预处理器macros中用于在单个语句中评估多个expression式。 这通常是为了让一个macros可以做更多的事情,而且仍然是一个单一的expression式,所以macros将适合只允许expression式的地方。

逗号运算符是一个非常危险的运算符,这个运算符的定义是:只允许一个被允许的事情。 这几乎总是很丑,但有时候就是这样。 这是您唯一使用它的时间 – 如果您有其他select,请勿使用逗号运算符。

在我头脑中,我想不出有太多其他的理由来使用操作符,因为在大多数其他情况下,通过在单独的语句中评估expression式可以得到类似的效果(虽然我确信有人会评论另一个我忽略的用法)。