似乎一般来说,在C(以及许多其他语言)中,人们也可以这样做,例如:
if (x > 0){
y = value1;
}
else{
y = value2;
}
或
y = (x>0)*value1 + (x <= 0)*value2;
第一种情况在风格上似乎更好,因为它更容易阅读(对大多数人来说?)。但是,第二种情况再次紧凑。更重要的是,性能有何不同?似乎第二种情况可能更慢,因为两个布尔表达式都被计算,并且有一个乘以零..但是,我隐约回想起如果语句有一些小的额外开销?我意识到我实际上可以衡量速度,但希望有人有一个更一般的答案。
答案 0 :(得分:2)
y = (x>0)*value1 + (x <= 0)*value2;
这是可怕的代码,不应该写(你需要100%确定比较运算符返回1
为“true”;是否是这样的情况需要很多东西)。
这就是C语言中三元运算符的用途:
y = (x > 0) ? value1 : value2;
更重要的是,性能有何不同?
我很想就“重要性”发表争论,但是:
没有。如果编译器值得,则三元运算符应扩展为与if
构造相同的字节码。你的y=(cond)*a+(!cond)*b
构造更可能变慢,因为乘法的奇怪滥用;但是,无论如何,现代的优化编译器可能会杀死它。
答案 1 :(得分:1)
使用if
所涉及的性能损失是由于它涉及分支。然而,像(x> 0)这样的表达式最可能也涉及分支。另外,正如您所提到的,在您的单个表达式中,您正在评估两个不同的条件,而在if
中,您只评估一个条件。正如其他人所提到的,编译器可能会将单个表达式和if
优化为相同的代码。最终,if
要好得多,因为它清楚它正在做什么。正如@Ed所提到的,如果要优化性能,请进行性能分析。然后,您可以专注于代码中花费最多时间的部分。
答案 2 :(得分:1)
正确性的第一个代码,然后为了清楚起见(当然,这两个经常连接!)。最后,只有你有真正需要的实证证据,你才能看到优化。过早的优化确实是邪恶的。优化几乎总是花费您的时间,清晰度和可维护性。你最好确定你买了一些有价值的东西。
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()
为true,因此编译器将在分支后立即放置真实代码,并在分支指令内放置假代码。这样编译器就可以实现优化。但是不要盲目使用likely()
和unlikely()
宏。如果预测是正确的,则意味着跳转指令的周期为零,但如果预测错误,那么将需要几个周期,因为处理器需要刷新它的管道,这比没有预测更糟糕。