"Narrowing conversion from 'int' to 'char' inside { }" 用于交叉编译时的合法值
"Narrowing conversion from 'int' to 'char' inside { }" for legal values when cross compiling
我有一个 C++ 项目,我在我的机器上使用 g++
编译(编译为 "host")并使用交叉编译器编译为 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
)是合法的,不会导致两个编译器出错。
Since the value is legal
你怎么知道的? char
s 符号是实现定义的。如果它是未签名的,则您的代码因缩小而格式错误 - §8.5.4/7:
A narrowing conversion is an implicit conversion
[…]
(7.4) —
from an integer type […] to an integer type
that cannot represent all the values of the original type, except
where the source is a constant expression whose value after integral promotions will fit into the target type.
§8.5.1/2:
If the initializer-clause is an expression and a narrowing conversion (8.5.4) is required to convert the expression, the program is ill-formed.
但是,如果您需要签名 char
,请使用 signed char
。
signed char c[1] = {-108};
…保证有效。
当您将变量声明为 char
时,它是有符号的还是无符号的取决于实现。如果您需要能够存储负值,您应该显式声明它 signed
,而不是依赖于实现定义的默认值。
signed char c[1] = { -108 };
这个应该更好:
signed char c[] = { (signed char)(-108) };
因为在括号中的值默认情况下可以被视为 int。
我在使用 crosstool-ng 的 arm 交叉编译器中编译 binutils 时遇到了类似的情况,尽管我的错误是:
i386.cc:3165:31: error: narrowing conversion of '144' from 'int' to 'char'
由于 144 大于 -128 到 127 的有符号字符范围,我不得不将受影响的行和函数的 return 更改为 unsigned char。
我还需要在函数的 return 中使用 reinterpret_cast 因为结果被用来形成一个字符串序列.然后编译正确。
所有 8 位值都可以通过 char
对象(在典型的现代硬件上)清楚地表示,因此分配这样的值应该是安全的 (*)。
如果文字是 char
类型,编译器不会发出警告。 escape sequence 允许您提供十六进制数作为字符文字:
int main(void) {
char c[1] = {'\x94'};
}
在有符号或无符号 char
(example) 的系统上,这将编译而不会触发 -Wnarrowing
。
(*) 此处安全意味着不会丢失任何信息,尽管该值可能不是您所期望的值:-108 如果 char
已签名且 148 是 char
未签名。
我有一个 C++ 项目,我在我的机器上使用 g++
编译(编译为 "host")并使用交叉编译器编译为 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
)是合法的,不会导致两个编译器出错。
Since the value is legal
你怎么知道的? char
s 符号是实现定义的。如果它是未签名的,则您的代码因缩小而格式错误 - §8.5.4/7:
A narrowing conversion is an implicit conversion
[…]
(7.4) — from an integer type […] to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.
§8.5.1/2:
If the initializer-clause is an expression and a narrowing conversion (8.5.4) is required to convert the expression, the program is ill-formed.
但是,如果您需要签名 char
,请使用 signed char
。
signed char c[1] = {-108};
…保证有效。
当您将变量声明为 char
时,它是有符号的还是无符号的取决于实现。如果您需要能够存储负值,您应该显式声明它 signed
,而不是依赖于实现定义的默认值。
signed char c[1] = { -108 };
这个应该更好:
signed char c[] = { (signed char)(-108) };
因为在括号中的值默认情况下可以被视为 int。
我在使用 crosstool-ng 的 arm 交叉编译器中编译 binutils 时遇到了类似的情况,尽管我的错误是:
i386.cc:3165:31: error: narrowing conversion of '144' from 'int' to 'char'
由于 144 大于 -128 到 127 的有符号字符范围,我不得不将受影响的行和函数的 return 更改为 unsigned char。
我还需要在函数的 return 中使用 reinterpret_cast
所有 8 位值都可以通过 char
对象(在典型的现代硬件上)清楚地表示,因此分配这样的值应该是安全的 (*)。
如果文字是 char
类型,编译器不会发出警告。 escape sequence 允许您提供十六进制数作为字符文字:
int main(void) {
char c[1] = {'\x94'};
}
在有符号或无符号 char
(example) 的系统上,这将编译而不会触发 -Wnarrowing
。
(*) 此处安全意味着不会丢失任何信息,尽管该值可能不是您所期望的值:-108 如果 char
已签名且 148 是 char
未签名。