【问题标题】:One line assignment according condition in c/c++在 c/c++ 中根据条件进行一行赋值
【发布时间】:2012-05-09 03:13:51
【问题描述】:

你好,

我想知道这些作业中哪一项更快、更安全、更好等,可能是为什么:

int choice = fgetc(stdin);
unsigned int bSize;

choice = fgetc(stdin)

1:

bSize = (choice == 'y' || choice == 'Y') ? 256 : 128;

2:

bSize = 128 + ((choice == 'y' || choice == 'Y') << 7);

谢谢。

【问题讨论】:

  • 从文件中读取字符将超过执行任一行所需的时间。
  • 当然 1 更具可读性。在这种情况下编译器生成的任何东西都不太可能对性能产生明显影响。
  • @DCoder: +1 - 在这种情况下,可读性比假设的(和过早的)微优化更重要

标签: c conditional variable-assignment


【解决方案1】:

关于速度,这至少与选择 2 一样快:

bSize = 128 << (choice == 'y' || choice == 'Y');

那个是否会比选择 1 更快对我来说不是很明显。但是,为了在未知平台上调整性能,我认为我喜欢选项 2 的建议变体。原因是,在硬件级别,选项 2(原始或变体)不涉及重新加载程序计数器,而是调用相对简单的移位寄存器操作,涉及的晶体管相对较少。 (实际上,如果您想真正了解它的技术性,我可以理解这种转变可能是通过多路复用来完成的。对于目前的格式来说,细节太多了,但重点是(choice == 'y' || choice == 'Y') 的输出被有效地直接传送到多路复用器的控制线之一。无论如何,它真的很快。)

关于是否可以按照建议的方式安全地使用评估条件,ISO/IEC 9899:1999 (E),第 1 节。 6.5.14.3,保证可以安全地做到这一点。其内容为:“|| 运算符如果任一操作数比较不等于 0,则应产生 1;否则,它产生 0。结果的类型为 int。”

(@PaulR 正确地观察到,像这个答案提供的那些电子理论考虑并不是决定性的。必须在实际平台上分析实际代码以确定哪个更快。这也不仅仅是@PaulR 的一个小问题. 可以说选择 2 更快,但这并不意味着 更快。​​取决于所使用的 CPU、分支预测或其他硬件可以促进选择 1,如果确实如此,我也不会感到非常惊讶。)

【讨论】:

  • 是的,我想这样会比选择 2 更快,但使用评估条件作为变量仍然是 100% 安全吗?
  • -1:您真的无法对上述示例的效率做出任何一般性预测,尤其是在不了解特定编译器或平台的情况下
  • @Neko:很安全。我已经修改了上面的答案来解释原因。
  • @PaulR:哇,你是个难缠的观众。当然你是对的,但是一般 electronic 原则确实可以承担,无论 C 标准是否保证它们的性能。我怀疑多路复用位移比调用 CPU 的分支预测硬件便宜,尤其是在品牌预测器猜错并且必须刷新管道的情况下。但我知道什么?不过,您的观点是正确的(尽管我承认我对否决票有点脾气暴躁)。
  • @thb:对不起,但这是我的一个小烦恼——对性能做出盲目的假设/预测,特别是在不考虑编译器和 CPU 的情况下,是最糟糕的过早优化。如果在特定情况下性能确实很重要,那么profile不同的选项 - 以衡量性能的形式提供的证据比猜测更有用。
【解决方案2】:

在我看来,“选择 1”“更快”,因为在比较之后只完成了一次赋值操作。在“选择 2”中,它执行“+”和“

【讨论】:

  • 唯一的问题是选项 1 使用了分支(一些比较和跳转指令),而选项 2 则没有。
  • @Neko:你无法知道编译器是否会使用分支,或者在不知道平台等细节的情况下对分支的惩罚可能是什么
  • -1:如果不考虑编译器和平台,所有预测都是没有意义的
  • [对不起,cmets 不允许换行]亲爱的 Neko,我明白你的想法。但是看看 'gcc' 使用 '-S' 选项生成的代码: 选择 1: movl %eax, -4(%rbp) cmpl $121, -4(%rbp) je .L2 cmpl $89, -4(%rbp ) jne .L3 .L2: movl $256, %eax jmp .L4 .L3: movl $128, %eax .L4: movl %eax, -8(%rbp) movl $0, %eax leave 选择2: movl %eax, - 4(%rbp) cmpl $121, -4(%rbp) je .L2 cmpl $89, -4(%rbp) jne .L3 .L2: movl $1, %eax jmp .L4 .L3: movl $0, %eax .L4 : sall $7, %eax subl $-128, %eax movl %eax, -8(%rbp) movl $0, %eax leave 请参阅这两种情况下的 L4 部分。选择权在你。
  • 是的,我同意 Paul R,它是平台和/或编译器特定的。
猜你喜欢
  • 1970-01-01
  • 2016-12-01
  • 2016-11-16
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多