"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};
}

这个程序似乎是正确的,因为 -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)是合法的,不会导致两个编译器出错。

Since the value is legal

你怎么知道的? chars 符号是实现定义的。如果它是未签名的,则您的代码因缩小而格式错误 - §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 未签名。