假设我有一堆整数(10〜20),需要检查它们是否等于0。最有效的方法是什么?我不想评估一个巨大的if(a = 0 || b = 0 || c = 0 || ...)语句。我想到过if(a b c ... = 0),但是如果我没记错的话,乘法并不是一个非常快的过程。还有其他技巧,例如按位操作会起作用吗?我正在尝试尽可能降低级别,以使此超级高效。
答案 0 :(得分:3)
我很确定最快,最清晰的方法是使用显式测试:
int has_zero = !a || !b || !c || !d || !e ...;
由于||
和&&
是C中的短路运算符,因此一旦知道最终结果,评估就会立即停止,因此,例如b
变量为零,该表达式满足true并停止对其余表达式的求值。
@AbhayAravinda建议!(a && b && c && d ...)
可能会更有效,但我不这么认为。因为这不是执行显式的not操作,而是针对零的低级别测试,所以对于几乎所有可靠地执行的体系结构来说,这都是一个非常容易的测试。我快速浏览了两个版本的优化汇编程序,但没有明显的性能赢家,但我认为第一个版本更清晰。
如果每个周期都很重要,那么请检查平台上的两个版本,但是在我的64位Intel系统上,gcc和clang实际上确实为两个版本生成了相同的程序集(启用了优化功能)。
简单的测试代码:
int a, b, c, d, e, f;
int test_or()
{
return !a || !b || !c || !d || !e || !f;
}
int test_and()
{
return ! (a && b && c && d && e && f);
}
int main()
{
return test_or() | test_and();
}
使用gcc -S -O testfile.c
进行编译,然后查看生成的.s
文件。
答案 1 :(得分:1)
依次测试每个。利用||
的短路属性;将变量按照每个变量为零的概率的降序排列:
if (!a/*most likely to be zero*/ || !b || ...){
// one of them is zero
}
答案 2 :(得分:0)
大多数人给出的答案如下:
!a || !b || ...
(其中a
是最可能为零的一个)
这样的想法是,在a
为零的情况下,将不评估序列的其余部分(由于不必要),这是编译器执行的一种优化。
这使问题变成了:您的编译器是否执行了此优化(如果是“可能的话”,执行此优化的参数是什么)?
您能告诉我们您正在使用哪个编译器(版本)吗?这可能使我们能够验证这一点。
答案 3 :(得分:0)
您可能会看到汇编器输出。
!a || !b || !c || !d || !e || !f
将为您提供一堆cmp
和je
语句。每个变量一对。由于布尔快捷方式评估,它可能运行得非常快。是否。
也许更好的确定性解决方案是使用按位AND运算符。如果一个操作数为0,则结果将为0。所以类似:
if (a & b & c & d & e & f & g & h & i & j & k)
将为每个变量生成一个mov
,然后是and
语句。
因此,如果为0的变量位于if语句的后半部分,则bitweise AND将更快。