マシン上でg++
を使用して(「ホスト」にコンパイル)、クロスコンパイラーを使用してARMプロセッサーに)(私の場合はarm-cortex_a8-linux-gnueabi-g++
)。私はC++ 0x/11標準への変換を行っていますが、初期化リストをコンパイルするとエラーが発生しますが、次のスニペットで再現できました。
int main(void) {
char c[1] = {-108};
}
-108
はchar
の正当な値であるため、このプログラムは正しいようです。 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
)を使用することは正当であり、両方のコンパイラでエラーが発生しないことに注意してください。
変数をchar
として宣言すると、その変数が署名されているか署名されていないかは実装に依存します。負の値を格納できるようにする必要がある場合は、実装定義のデフォルトに依存するのではなく、signed
を明示的に宣言する必要があります。
signed char c[1] = { -108 };
値は正当であるため
どうやってわかったの? char
s signednessは実装定義です。署名されていない場合、コードはナローイングによって不正な形式になります-§8.5.4/ 7:
縮小変換は暗黙的な変換です
[…]
(7.4)— 整数型[…]から元の型のすべての値を表すことができない整数型へ。ただし、ソースが整数の後の値を持つ定数式である場合を除くプロモーションはターゲットタイプに適合します。
§8.5.1/ 2:
initializer-clauseが式であり、式を変換するために絞り込み変換(8.5.4)が必要な場合、プログラムの形式は正しくありません。
ただし、署名済みのchar
が必要な場合は、signed char
。
signed char c[1] = {-108};
…機能することが保証されています。