web-dev-qa-db-ja.com

「{}内の 'int'から 'char'への狭い変換」、クロスコンパイル時の正当な値

マシン上でg++を使用して(「ホスト」にコンパイル)、クロスコンパイラーを使用してARMプロセッサーに)(私の場合はarm-cortex_a8-linux-gnueabi-g++)。私はC++ 0x/11標準への変換を行っていますが、初期化リストをコンパイルするとエラーが発生しますが、次のスニペットで再現できました。

int main(void) {
    char c[1] = {-108};
}

-108charの正当な値であるため、このプログラムは正しいようです。 g++でこれをコンパイルしても、次のコマンドラインではエラーは発生しません。

g++ example.cc -std=c++0x

ただし、クロスコンパイラでコンパイルすると、次のようになります。

arm-cortex_a8-linux-gnueabi-g++ example.cc -std=c++0x

次のエラーが表示されます。

example.cc: In function 'int main()':
example.cc:2:22: error: narrowing conversion of '-0x0000000000000006c' from 'int' to 'char' inside { } [-fpermissive]

値は正当であるため、これはバグのように見えます。このエラーが発生する理由と、それを解決する方法を説明できますか?

編集:正の値(たとえば、108)を使用することは正当であり、両方のコンパイラでエラーが発生しないことに注意してください。

13
Andy Thomas

変数をcharとして宣言すると、その変数が署名されているか署名されていないかは実装に依存します。負の値を格納できるようにする必要がある場合は、実装定義のデフォルトに依存するのではなく、signedを明示的に宣言する必要があります。

signed char c[1] = { -108 };
20
Barmar

値は正当であるため

どうやってわかったの? chars signednessは実装定義です。署名されていない場合、コードはナローイングによって不正な形式になります-§8.5.4/ 7:

縮小変換は暗黙的な変換です
[…]
(7.4)— 整数型[…]から元の型のすべての値を表すことができない整数型へ。ただし、ソースが整数の後の値を持つ定数式である場合を除くプロモーションはターゲットタイプに適合します。

§8.5.1/ 2:

initializer-clauseが式であり、式を変換するために絞り込み変換(8.5.4)が必要な場合、プログラムの形式は正しくありません。

ただし、署名済みのcharが必要な場合は、signed char

signed char c[1] = {-108};

…機能することが保証されています。

9
Columbo