三元运算符与数组?
在 C 中,索引数组是否比?:运算符更快?
例如,会(const int[]){8, 14}[N > 10]比N > 10? 14 : 8?
回答
坚持使用三元运算符:
- 更简单
- 输入的字符更少
- 更容易阅读和理解
- 它更易于维护
- 它可能不是您应用程序中的主要瓶颈
- 对于CPU,这是一个简单的比较
- 编译器很聪明,如果数组解决方案更快,编译器就会为两种变体生成相同的代码
强制性报价(强调我的):
程序员浪费了大量时间来考虑或担心他们程序中非关键部分的速度,而在考虑调试和维护时,这些提高效率的尝试实际上会产生强烈的负面影响。
我们应该忘记小效率,比如大约 97% 的时间:过早的优化是万恶之源。然而,我们不应该放弃我们在关键的 3% 中的机会— Donald Knuth • https://wiki.c2.com/?PrematureOptimization
现在,让我们比较一下编译器实际生成的内容。
#include <stdlib.h>
int ternary(int n) { return n > 10 ? 14 : 8; }
int array(int n) { return (const int[]){8, 14}[n > 10]; }
在 Ubuntu 中使用 (g)cc 10.2.1 编译并启用优化:
$ cc -O3 -S -fno-stack-protector -fno-asynchronous-unwind-tables ternary.c
-S编译后停止,不汇编。您最终会得到一个.s包含生成的汇编代码的文件。(这些-fno…标志是为了禁用我们的示例不需要的额外代码生成)。
ternary.s 汇编代码,与删除的方法无关的行:
ternary:
endbr64
cmpl $10, %edi
movl $8, %edx
movl $14, %eax
cmovle %edx, %eax
ret
array:
endbr64
movq .LC0(%rip), %rax
movq %rax, -8(%rsp)
xorl %eax, %eax
cmpl $10, %edi
setg %al
movl -8(%rsp,%rax,4), %eax
ret
.LC0:
.long 8
.long 14
如果比较它们,您会注意到阵列版本的指令更多:6 条指令与 4 条指令。没有理由编写每个开发人员必须阅读两次的更复杂的代码;较短和直接的代码编译为更高效的机器代码。