[英]How can I rewrite this if-else statement so that it doesn't use a jump?
我不是要优化任何东西,所以请不要告诉我,过早的优化是万恶之源。 我试图解决一个问题,我找不到第三个解决方案。
问题是这样的:
if (x)
y = a;
else
y = b;
x
只能是0或1.如何在没有跳转的情况下写出这个条件?
一种具有数据结构的解决方案是:
int temp[2] = {b, a};
y = temp[x];
另一种算术解决方案是
y = x * a + (1 - x) * b;
应该有第三个,一个逻辑解决方案。 你知道它的样子吗? 请用C解决。
y = a ^ ((x - 1U) & (a ^ b));
这使用按位x或
你是说你不想跳转源代码或CPU级别?
在我的编译器上
int choose(int x, int a, int b)
{
int y;
if (x)
y = a;
else
y = b;
return y;
}
汇编到此 -
test ecx, ecx
cmovne r8d, edx
mov eax, r8d
ret 0
虽然我在C代码级别编写了一个跳转,但生成的机器代码中没有一个,因为编译器能够使用条件移动指令。
这可能不是最好的解决方案,但我认为它是没有跳跃的按位等价物:
y = (~(x*UINT_MAX) & a) | (~(1 - x) & b);
下面的代码使用的技巧是,当x
为1或0时, x-1
为0或-1(也就是0xFFFFFFFF,假设32位int:s)。 如果x
为1,则&
的结果为零,因此结果为a
。 当x
为零时, &
的结果为ba
,则总结果将为a+(ba)
或简单为b
。
int test(int x, int a, int b)
{
return a + ( (((unsigned int)x)-1) & (b - a) );
}
在一个虚构的微控制器(没有任何花哨的条件移动指令),这将导致四个指令:
ADD #-1 R12
SUB R13, R14
AND R14, R12
ADD R13, R12
不可否认,这与@ 6502发布的XOR解决方案非常相似。
那么选择功能呢?
#include <stdio.h>
int choose(unsigned int x, int a, int b)
{
unsigned int selector = -x;
return (a & selector) | (b & ~selector);
}
int main()
{
printf("%d\n", choose(0, 123, 200));
printf("%d\n", choose(1, 123, 200));
}
使用三元?:
运算符。 这是为了这个。
我同意Jens的观点; 一个三元运算符可以在没有跳跃的情况下完成这一操作。
y = x ? a : b
顺便说一句,有一个姊妹网站Code Golf ,在那里人们会问自然的问题“如何在保持约束条件的同时用最短的代码解决问题x?”
对于允许条件执行语句的处理器:
y = a;
if (x != 0) y = b;
在32位模式的ARM处理器上,这应该转换为以下伪指令:
mov y, a; move a into y.
test x; (or XOR X, X ; to set condition codes)
MOVNZ y, b ; move b into y if condition is non-zero.
这里没有跳转,至少在汇编语言级别。
注意:特定于平台的解决方案可能对没有条件指令执行功能的处理器有效。
switch (x) {
case 1:
y = a;
break;
default:
y = b;
break;
}
编辑:原来的问题说“有跳”......不是“没有”
编辑:我误读了一个问题,即C代码根本不应该使用跳转。
我想我会一起去
y = b;
if (x)
y = a;
如果我正确阅读下面的反汇编代码,那么应该只有一个跳转:
0000000000400474 <main>:
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: 8b 45 fc mov -0x4(%rbp),%eax
40047b: 89 45 f8 mov %eax,-0x8(%rbp)
40047e: 83 7d f4 00 cmpl $0x0,-0xc(%rbp)
400482: 74 06 je 40048a <main+0x16>
400484: 8b 45 f0 mov -0x10(%rbp),%eax
400487: 89 45 f8 mov %eax,-0x8(%rbp)
40048a: c9 leaveq
40048b: c3 retq
40048c: 90 nop
40048d: 90 nop
40048e: 90 nop
40048f: 90 nop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.