16

次のことを考慮してください。

inline unsigned int f1(const unsigned int i, const bool b) {return b ? i : 0;}
inline unsigned int f2(const unsigned int i, const bool b) {return b*i;}

の構文f2はよりコンパクトですが、標準はそれを保証しf1f2厳密に同等ですか?

bさらに、コンパイル時にとがわかっている場合にコンパイラにこの式を最適化させたい場合i、どのバージョンを選択する必要がありますか?

4

4 に答える 4

13

ええ、はい、両方とも同等です。boolは整数型であり、整数コンテキストでのtrue変換が保証されていますが、への変換が保証されています。1false0

(逆もまた真です。つまり、ゼロ以外の整数値はブールコンテキストで変換されることが保証されtrue、ゼロ整数値はブールコンテキストで変換されることが保証されfalseます。)

符号なしの型を使用しているので、他の、おそらくビットハックベースでありながら完全に移植可能な同じものの実装を簡単に思い付くことができます。

i & -(unsigned) b

ただし、適切なコンパイラは、どのバージョンでも、それ自体で最適な実装を選択できるはずです。

PS驚いたことに、GCC 4.1.2は、3つのバリアントすべてを事実上文字通りにコンパイルしました。つまり、乗算ベースのバリアントでマシン乗算命令を使用していました。cmovneバリアントの命令を使用してブランチレスにするのに十分賢い?:ので、おそらく最も効率的な実装になりました。

于 2012-12-25T22:44:13.357 に答える
6

はい。あなたがそうするように式で使用され、保証されている場合、それはであると仮定するのは安全trueです:1false0

C ++ 11、インテグラルプロモーション、4.5

bool型の右辺値は、int型の右辺値に変換でき、falseは0になり、trueは1になります。

于 2012-12-25T22:48:35.643 に答える
1

コンパイラは暗黙の変換を使用してunsigned intfromを作成するbため、はい、これは機能するはずです。単純な乗算による条件チェックをスキップしています。どちらがより効果的/高速ですか?わからない。優れたコンパイラは、おそらく両方のバージョンを最適化すると思います。

于 2012-12-25T22:40:56.300 に答える
0

FWIW、次のコード

inline unsigned int f1(const unsigned int i, const bool b) {return b ? i : 0;}
inline unsigned int f2(const unsigned int i, const bool b) {return b*i;}

int main()
{
    volatile unsigned int i = f1(42, true);
    volatile unsigned int j = f2(42, true);
}

gcc -O2でコンパイルすると、次のアセンブリが生成されます。

    .file   "test.cpp"
    .def    ___main;    .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 2,,3
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB2:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $42, 8(%esp)   // i
    movl    $42, 12(%esp)  // j
    xorl    %eax, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE2:

ご覧のとおり、f1またはのどちらもあまり残っていません。f2

C ++標準に関する限り、コンパイラーは、観察可能な動作(ルールのように)を変更しない限り、最適化に関して何でも行うことができます。

于 2012-12-25T23:27:58.790 に答える