基于布尔值的 C 评估 - 哪个更快,哪个风格更好?

C evaluation based on boolean - which is faster, which is better style?

似乎在一般情况下,在 C(和许多其他语言)中,人们同样可以做到这一点,例如:

if (x > 0){
    y = value1;
}
else{
    y = value2;
}

y = (x>0)*value1 + (x <= 0)*value2;

第一种情况在文体上似乎更好,因为它更易于阅读(对大多数人而言?)。但话又说回来,第二种情况更紧凑。更重要的是,性能有什么不同吗?似乎第二种情况可能会更慢,因为两个布尔表达式都被评估了,并且乘以零..但是,我依稀记得 if 语句有一些小的额外开销?我意识到我实际上可以测量速度,但希望有人能给出更笼统的答案。

y = (x>0)*value1 + (x <= 0)*value2;

这是糟糕的代码,不应该被编写(您需要 100% 确定比较运算符 return 1 for "true";是否案例受制于很多东西)。

这就是类 C 语言中的 三元运算符 的用途:

 y = (x > 0) ? value1 : value2;

More importantly, is there any difference in performance?

我很想就 "importance" 进行辩论,但是:

没有。如果编译器值得的话,三元运算符应该扩展为与 if 构造相同的字节码。你的 y=(cond)*a+(!cond)*b 构造更有可能变慢,因为奇怪的乘法滥用;但话又说回来,现代的优化编译器可能会杀死它,无论如何。

使用 if 所涉及的性能损失是由于它涉及分支这一事实。但是,像 (x > 0) 这样的表达式很可能也涉及分支。此外,正如您所提到的,在您的单个表达式中,您正在评估两个不同的条件,而在 if 中您只评估一个。正如其他人所提到的,编译器可能会将单个表达式和 if 优化为相同的代码。最终,if 要好得多,因为它很清楚它在做什么。正如@Ed 提到的,如果您想优化性能,请进行分析。然后您可以专注于花费最多时间的代码部分。

首先是正确性代码,然后是清晰性代码(当然,这两者通常是相关联的!)。最后,只有当你有实际需要的真实经验证据时,你才能考虑优化。过早的优化真的是邪恶的。优化几乎总是会花费您时间、清晰度和可维护性。你最好确定你买的是物有所值的东西。

y = (x>0)*value1 + (x <= 0)*value2;

不要在您的任何代码中使用它。这是关于如何编写 terrible 代码的一个很好的例子,因为它根本不直观。此外,您是否会获得任何性能提升取决于您的机器架构(取决于您的架构 multiplication instruction 所采用的周期数)。

但是,C 和 C++ 中的条件语句(例如 if else)在最低级别(在硬件中)是昂贵的。要了解原因,您必须了解 pipelines 的工作原理。它会导致管道刷新并降低处理器的效率。

Linux kernel对条件语句使用优化技术,__builtin_expect。在使用条件语句(if-else 语句)时,我们通常知道哪个分支为真,哪个分支不为真(最有可能)。如果编译器提前知道这些信息,它就可以生成最优化的代码。

#define likely(x)      __builtin_expect(!!(x), 1)
#define unlikely(x)    __builtin_expect(!!(x), 0)

if (likely(x > 0)) {
    y = value1;
} else {
    y = value2;
}

对于上面的例子,我已经将if条件标记为likely()真,所以编译器会将真代码紧跟在分支之后,而假代码放在分支指令中。这样编译器就可以实现优化。但不要盲目使用 likely()unlikely() 宏。如果预测正确,则意味着跳转指令的周期为零,但如果预测错误,则需要几个周期,因为处理器需要刷新其流水线,这比没有预测更糟糕。