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

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

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

但我假设您的程序中没有不必要的标志。所以我建议做借调的,它更高效、更优雅,即使看起来不是这样。

于 2013-07-20T05:18:39.767 回答
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。

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

快乐编码!

于 2013-07-20T06:57:42.410 回答
1

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

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

即使它看起来不好看,它也正是你想要的。

于 2013-07-20T11:53:07.573 回答
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 回答