[英]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.