可读条件逻辑没有不必要的执行?

时间:2013-07-19 23:47:05

标签: c

我正在尝试使下面的代码既可读又具有高效性。我想避免对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
    }
}

6 个答案:

答案 0 :(得分:3)

你可以这样做:

void foo(int flagA)
{
    int flagB;

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

答案 1 :(得分: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
    }
}

答案 2 :(得分:1)

我无法明确地说什么,因为我没有看到任何实际的代码,但在我看来,flagA是无关紧要的,可以忽略。虽然必须评估flagB,因为它是相关的并导致代码更改。

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

但我假设您的程序中没有不必要的标记。所以我建议做一个借调的,它更有效和优雅,即使它看起来不那样。

答案 3 :(得分: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则添加额外的函数调用开销。

他们都是有效的解决方案恕我直言。这只是一个可读性和您希望代码表现如何的问题,更不用说避免代码重复......没人喜欢! : - )

快乐的编码!

答案 4 :(得分:1)

如果您真的不想封装getFlagB调用或拆分if,则可以滥用逗号运算符:

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

即使看起来不太好,但它确实是你想要的。

答案 5 :(得分: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();
}