簡體   English   中英

我怎樣才能重寫這個if-else語句,以便它不使用跳轉?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM