我知道不能将char值表示为176,但是某些字节系统是无符号的(0-255),而另一些字节系统则是有符号的(-128至127)。在这种情况下,我使用的是unsigned,所以我只想创建一个简单的字节消息数组,但是当尝试放置一个大于127的值时出现此错误,但是如果我首先将其声明为int,则可以避免该错误。有人可以详细解释为什么这样做吗?
方法1:不起作用。我收到此错误消息:将“ 176”的转换范围从“ int”转换为“ char”
char m1[3]{ 176, 118, 1 };
方法2:有效
int b1 = 176;
char m1[3]{ b1, 118, 1 };
答案 0 :(得分:3)
在使用花括号进行初始化(又称为“统一初始化”)时,则不允许缩小转换。否则,值将被静默截断。
大多数编译器都有警告选项,您可以启用这些警告选项,以捕获发生截断的许多(但不是全部)实例。他们通常还具有可以将此类警告变为错误的选项。 您应该使用这些选项。
如果要使用字节,那么std::byte可以说是正确的类型。或者(如果无法使用)std::uint8_t。
答案 1 :(得分:1)
这两种情况都是不正确的,但是正如我在my answer here中所解释的那样,仅需要诊断。该诊断是警告还是错误取决于实施。因此,这非常符合要求。
例如,在这种情况下,gcc对第一个错误产生错误,而对第二个错误仅产生警告(see it live on godbolt):
error: narrowing conversion of '176' from 'int' to 'char' [-Wnarrowing]
2 | char m1[3]{ 176, 118, 1 };
| ^
warning: narrowing conversion of 'b1' from 'int' to 'char' [-Wnarrowing]
5 | char m2[3]{ b1, 118, 1 };
| ^
这是标准允许的,我将引用this gcc bug report的relevent部分:
该标准仅要求“合格的实施方案应发出至少一条诊断消息”,因此允许使用警告编译程序。正如安德鲁所说,-Werror = narrowing允许您根据需要将其设置为错误。
G ++ 4.6给出了一个错误,但有意将其更改为4.7,因为许多人(包括我本人)发现缩小转换是尝试将大型C ++ 03代码库编译为C +时最常见的问题之一。 +11。以前格式良好的代码,例如char c [] = {i,0}; (我只会在char范围内)导致错误,因此必须将其更改为char c [] = {(char)i,0}
同时使用gcc和clang,您可以使用-Werror
将所有警告变为错误。
答案 2 :(得分:0)
大多数系统上的典型字符范围:
char
是 signed 还是 unsigned 是实现定义的。您可以使用std::is_signed<char>()
进行检查。在您的情况下,它是隐式的 signed ,编译器检测到您正在隐式地将正整数(10110000 = 176)转换为带符号的字符值(其中10110000为-90)。如果值小于或等于127,则不会生成警告(尝试!)。
如果要避免隐式转换(缩小转换),可以显式指定其为 unsigned :
unsigned char m1[3]{ 176, 118, 1 };
如果要使用签名字符,则最好使用signed
修饰符,而不要依赖于实现:
signed char m1[3]{ b, 118, 1 }; // where b is less than or equal to 127
通过{}初始化,编译器应该-至少-将其诊断为警告,这会使程序格式错误。但是同样,这取决于所使用的编译器和选项。如果您转到https://gcc.godbolt.org/并使用不同的编译器/选项编译代码,则可能会发现差异。
一些例子:
对于以下代码:
char m1[3] = {176, 118, 1 };
error: narrowing conversion of '176' from 'int' to 'char' inside { } [-Wnarrowing]
。但是,当您使用标志-Wno-narrowing
时,您不会得到它,但程序仍然格式错误,并且您不希望这样做。-Wno-narrowing
或-Werror=narrowing
时,您会看到它分别被警告或错误拒绝。 使用代码:
int b1 = 176;
char m1[3] = {b1, 118, 1 };
您使用不同的编译器版本会得到不同的行为,但是程序仍然格式错误。
通常,应该指出,使用-Wnarrowing
,-Wall
或-Werror=narrowing
之类的选项与编译器的任何版本(我想,我都没有检查所有选项)缩小的转换范围,这意味着您的程序格式错误,并且您不希望这样做。
我希望这会有所帮助!