2013-07-19 21 views
5

我試圖讓下面的代碼可讀性和高性能。我想避免任何不必要的電話getFlagB(),同時也不會重複任何事情。下面我寫了兩種方法,每種都滿足這些標準中的一種。可讀的條件邏輯沒有不必要的執行?

假設getFlagB()不能以任何方式改變。有沒有辦法在C中同時滿足這兩個要求,而無需創建額外的標誌?

// Method 1 - doesn't repeat code blocks but calls getFlagB even when it may not need to 
void foo(int flagA) 
{ 
    int flagB; 
    getFlagB(&flagB); 

    if(flagA & flagB) 
    { 
     // Code block 0 
    } 
    else 
    { 
     // Code block 1 
    } 
} 

// Method 2 - doesn't no extra call to getFlagB, but repeats code block 1 
void foo(int flagA) 
{ 
    int flagB; 

    if(flagA) 
    { 
     getFlagB(&flagB); 
     if(flagB) 
     { 
      // Code block 0 
     } 
     else 
     { 
      // Code block 1 
     } 
    } 
    else 
    { 
     // Code block 1 
    } 
} 
+1

重構所以getFlagB返回一個值,然後用'如果(FLAGA && getFlagB())' – John3136

+0

從這樣一個問題: 「假設getFlagB()不能以任何方式改變」 –

+2

將getFlagB換成另一個方法'int myGetFlagB(){int b; getFlagB(&b); return b;}' – John3136

回答

1

if之前明確計算條件。

_Bool condition = flagA; 

if (flagA) { /* First decide what to do. */ 
    _Bool flagB; 
    GetFlagB(& flagB); 

    condition = flagA && flagB; /* Prefer && over &. */ 
} 

if (condition) { /* Then do it. */ 
    Code1(); 
} else { 
    Code2(); 
} 
3

你可以這樣做:

void foo(int flagA) 
{ 
    int flagB; 

    if(flagA) 
    { 
     getFlagB(&flagB); 
     if(flagB) 
     { 
      // Code block 0 
      return ; 
     } 
    } 
    // code block 1 
} 
+1

請解釋一下爲什麼我至少被低估了? – nouney

+0

也許,因爲你沒有意識到,當條件爲真時,你的代碼按順序執行兩個塊,這不是OP想要的。 – cmaster

+0

@cmaster也許你沒有意識到你完全錯了。 – nouney

3

getFlagB()的另一種方法,然後讓編譯器把它清除出來給你。

int myGetFlagB() { int b; getFlagB(&b); return b; } 

void foo(int flagA) 
{ 
    /* note: assume you mean && and not &, otherwise there is no way 
    * to short circuit - you always need to call getFlagB for a 
    * bitwise AND. 
    */ 
    if(flagA && myGetFlagB()) 
    { 
     // Code block 0 
    } 
    else 
    { 
     // Code block 1 
    } 
} 
+1

或者,因爲逗號運算符表示序列點,您可以使用:'if(flagA &&(getFlagB(&flagB),flagB))...'。 – jxh

1

我不能確切地說任何事情,因爲我沒有看到任何實際的代碼,但在我看來,flagA是無關緊要的,可以忽略。雖然flagB必須進行評估,因爲它是相關的並導致代碼發生更改。

void foo() 
{ 
    getFlagB(&flagB) 
    if(flagB) 
    { 
     //Code 1 
    } 
    else 
    { 
     //Code 0 
    } 
} 

但我假設你沒有在你的程序中不必要的標誌。所以我會建議做一個更加高效和優雅的調派人士,即使認爲這似乎並不是這樣。

1

編輯

你也可以做到以下幾點,只要FLAGB被初始化爲0,這避免了在我前面,它假定標誌不能代碼塊0中修改發佈的代碼中的錯誤,這可能會導致代碼塊0和1執行。我建議你只是因爲你可能會在某個時候要修改內部FOO()標誌這個新:

int flagB = 0; 

if (flagA) 
    getFlagB(&flagB); 

if (flagA && flagB) { 
    // code block 0 
} else { 
    // code block 1 
} 

是,FLAGA測試兩次。你有三元條件,但你要求一組二進制結果。如果沒有像所提到的那樣使用序列點,則必須測試兩次或重複代碼或不必要地調用函數,或者如果flagA恰好設置,則會增加額外的函數調用開銷。

他們都是有效的解決方案恕我直言。這只是一個問題,你想要代碼的可讀性和表現如何,更不用說避免代碼重複了......沒人喜歡! :-)

快樂編碼!

1

如果你真的不想要麼封裝getFlagB來電或分割你的,如果,你可以濫用逗號操作符:

if(flagA && (getFlagB(&flagB), flagB)) { 

即使它看起來並不漂亮,但它正是你想要的。

+0

從問題:「我試着讓下面的代碼都是_readable_和performant。」 – nouney

+1

+1。用'void'返回類型和無償引用返回來定義函數時,可讀性消失。 – Potatoswatter