"在交叉编译时缩小从'int'到{}'内部'char'的转换,以获得合法值

And*_*mas 13 c++ linux cross-compiling c++11

我有一个C++项目,我g++在我的机器上编译(编译为"host")和使用交叉编译器的ARM处理器(在我的例子中)arm-cortex_a8-linux-gnueabi-g++).我正在转换为C++ 0x/11标准版,并且在编译初始化列表时出现错误,我可以在以下代码段中重现:

int main(void) {
    char c[1] = {-108};
}
Run Code Online (Sandbox Code Playgroud)

这个程序似乎是正确的,因为-108它的合法价值char.g++使用以下命令行进行编译时不会产生错误:

g++ example.cc -std=c++0x
Run Code Online (Sandbox Code Playgroud)

但是,当我使用交叉编译器进行编译时,如下所示:

arm-cortex_a8-linux-gnueabi-g++ example.cc -std=c++0x
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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

由于价值合法,这似乎是一个错误.你能解释一下为什么我会得到这个错误以及如何解决它?

编辑:请注意,使用正值(例如108)是合法的,并且不会导致两个编译器出错.

Bar*_*mar 21

当您将变量声明为时char,它依赖于实现,无论是有符号还是无符号.如果您需要能够存储负值,则应该signed明确声明它,而不是依赖于实现定义的默认值.

signed char c[1] = { -108 };
Run Code Online (Sandbox Code Playgroud)


Col*_*mbo 9

由于价值合法

你怎么知道?char签名是实施定义的.如果它没有签名,那么你的代码就会变窄 - §8.5.4/ 7:

缩小转换是隐式转换
[...]
(7.4) - 从一个整数类型[...]为整数类型,它可以不表示原始类型的所有值,除非源是一个常量表达式积分优惠后,其值将适合目标类型.

第8.5.1节/ 2:

如果initializer子句是表达式并且转换表达式需要缩小转换(8.5.4),则程序格式错误.

但是,如果您需要签名char,请使用signed char.

signed char c[1] = {-108};
Run Code Online (Sandbox Code Playgroud)

......保证有效.