禁止使用逗号运算符

9

我从不使用逗号操作符。但是有时候,当我写递归函数的时候,会犯一个愚蠢的错误:忘记函数名字。这就是为什么最后一个操作数被返回,而不是递归调用的结果。

以下是一个简单的例子:

int binpow(int a,int b){
    if(!b)
        return 1;
    if(b&1)
        return a*binpow(a,b-1);
    return (a*a,b/2); // comma operator
}

在编程中,是否可能出现编译错误而不是难以调试的错误代码?


6
太过了,你希望编译器为你做所有的工作吗? - Nawaz
3
@Nawaz,我想让编译出尽可能多的错误。 - RiaD
3
@Nawaz,我猜你会把所有的编译器信息都删掉吧?;-) - Jimmy
1
"return (a*a,b/2); // 逗号运算符" 这行代码应该让你感到惊恐并让你的眼睛发热。你不需要编译器错误,只需要_读取_这该死的一行代码。 - Daniel Daranas
1
@SteveLorimer 我明白。但是我认为有必要审查代码,最简单的代码审查就可以发现那个错误。 - Daniel Daranas
显示剩余2条评论
2个回答

21

有一个注意点,可以这样做。gcc编译器具有-Wunused-value警告(或使用-Werror则是错误)。由于a*a没有效果,因此会对您的示例产生影响。编译器结果:

test.cpp: In function ‘int binpow(int, int)’:
test.cpp:6:43: warning: left operand of comma operator has no effect [-Wunused-value]

不过,这样做无法捕获只有一个参数的调用以及所有参数都具有副作用的调用(比如 ++)。例如,如果你的最后一行代码如下所示:

return (a *= a, b/2);

由于逗号表达式的第一部分具有改变a的效果,因此不会触发警告。虽然编译器可以对其进行诊断(本地非易失性变量的赋值,在后续未使用),并且可能被优化掉,但是没有gcc警告。

完整的-Wunused-value手册条目为参考,其中Mike Seymours的引用已经突出显示:

每当语句计算显式未使用的结果时发出警告。要消除此警告,请将未使用的表达式转换为void类型。这包括不包含副作用的表达式语句或逗号表达式的左侧。例如,表达式x [i,j]将导致警告,而x [(void) i,j]则不会。


4
@Nawaz:当然,但逗号的左操作数没有作用并被忽略,这一点被-Wunused-value捕获。 - thiton
2
@Nawaz:他是对的。a*a很明显是一个未使用的值。 - Lightness Races in Orbit
6
@Nawaz: 我相当确定它是未使用的值,不管它是否在技术上是未使用的值,GCC选项都能够捕获到它。根据他们的文档所述:" 这包括一个没有副作用的表达式语句或逗号表达式的左侧。" - Mike Seymour
当然有,而且gcc会警告:warning: left operand of comma operator has no effect [-Wunused-value] - Damon
1
当然这是一个未使用的值。告诉我它在哪里被使用了;我敢打赌你找不到。 - Lightness Races in Orbit
显示剩余2条评论

2

gcc支持-Wunused-value参数,它可以在逗号操作符的左操作数没有副作用时发出警告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接