5

以下のコードを読みやすく、パフォーマンスの高いものにしようとしています。getFlagB()何も繰り返さないようにしながら、不要な呼び出しを避けたいと思います。以下に 2 つのメソッドを記述しましたが、それぞれがこれらの基準の 1 つを正確に満たしています。

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
    }
}
4

6 に答える 6

3

あなたはこれを行うことができます:

void foo(int flagA)
{
    int flagB;

    if(flagA)
    {
        getFlagB(&flagB);
        if(flagB)
        {
            // Code block 0
            return ;
        }
    }
  // code block 1
}
于 2013-07-19T23:55:52.483 に答える
2

別のメソッドでラップ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
    }
}
于 2013-07-20T00:20:45.080 に答える
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();
}
于 2013-07-20T13:16:26.423 に答える
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 は 2 回テストされます。三項条件がありますが、結果の二項セットを求めています。ある人が言及したようにシーケンス ポイントを使用しないと、2 回テストするか、コードを複製するか、不必要に関数を呼び出すか、flagA が設定された場合に余分な関数呼び出しのオーバーヘッドを追加する必要があります。

それらはすべて有効なソリューションです。コードの重複を避けることは言うまでもなく、コードをどれだけ読みやすく、どれだけうまく実行したいかだけの問題です...誰もそれを好きではありません! :-)

ハッピーコーディング!

于 2013-07-20T06:57:42.410 に答える
1

実際のコードを見たことがないので断言はできませんが、flagA は無関係で無視できるように思えます。一方、flagB は関連性があり、コードが変更されるため、評価する必要があります。

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

ただし、プログラムに不要なフラグがないことを前提としています。そのため、そのように見えなくても、より効率的でエレガントなセカンドを行うことをお勧めします。

于 2013-07-20T05:18:39.767 に答える