web-dev-qa-db-ja.com

ブール値をシフトすることは常に安全ですか?

私は誤って&ではなく&&を使用したというCppcheck警告(決定的な警告)につまずきました。

/// @param code identifies the command. Only the lower 16 bits of are being processed
int encodeCmdState(bool finished, int code, bool errorneous)
{
    return
        (finished & 1) |
        ((code & 0xffff)<<1) |
        ((err & 1)<< 17);
}

このコード(スタイル)がboolがCで利用できなかった時代に戻ったかどうかはわかりません。私の最初のアイデアは、boolの部分から& 1の正規化を単に取り除くことです。でも確かにしたいので...

シフトbool値は「ポータブル」および「セーフ」ですか?または、より一般的には:

implicitbool- to -int会話式の算術式always normalize値はありますか?

3
Wolf

C++標準に従って、§4.5広告。 6(統合プロモーションについて):

Bool型のprvalueはint型のprvalueに変換でき、falseはゼロになり、trueは1になります。

C++標準に従って、§4.7ad。 4(積分変換について):

宛先タイプがブールの場合は、4.12を参照してください。ソースタイプがブールの場合、値falseはゼロに変換され、値trueは1に変換されます。

したがって、整数の昇格と変換中に、ブール値trueは常に1に変換され、ブール値falseは常に0に変換されます。

例として、この単純で素朴な例( http://ideone.com/kgxrTW )を見てください。

#include <iostream>
using namespace std;

int main() {
    bool a = true;
    bool b = false;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << boolalpha << "a = " << a << endl;
    cout << boolalpha << "b = " << b << endl;

    int c = a << 1;
    int d = b << 1;
    bool e = a << 1;
    cout << "c = " << c << endl;
    cout << "d = " << d << endl;
    cout << "e = " << e << endl;
    return 0;
}

その出力は次のようになります:

a = 1
b = 0
a = true
b = false
c = 2
d = 0
e = true
5
Tommy Andersen

TommyAが指摘 のように、少なくとも通常の状況は安全です。

しかし、(入力から)bool値のチェックされていない割り当てを処理する場合は注意が必要です。たとえば、メモリ部分をコピーする場合(ナイーブIPCはstructsを使用します) 、これが問題になる可能性があると思ったので、この簡単なテストケースを作成しました。

#include <iostream>
#include <cstring>
using namespace std;

int b2i(bool v)
{
    return v << 1;
}

int main() {
    bool v = true;
    cout << "v = " << v << endl;
    cout << "b2i(v) = " << b2i(v) << endl;

    // simulating input:
    memset(&v, -1, sizeof v);

    cout << "b2i(v) = " << b2i(v) << endl;
    return 0;
}

いくつかのコンパイラで試してみました。実際、出力は異なります。

C++ 14 および C++ 4.9.2

v = 1
b2i(v) = 2
b2i(v) = 2

C++ 4.3.2(Borland 0x0564でも):

v = 1
b2i(v) = 2
b2i(v) = 510
1
Wolf