为什么将 256 分配给 char 会引发警告,但分配 255 不会,但两者都会导致整数溢出?
Why does assigning 256 to a char raise a warning, but assigning 255 don't, but both result in integer overflow?
考虑这个例子:
#include <iostream>
int main()
{
char c = 256;
std::cout << static_cast<int>(c);
}
发出警告:
warning: overflow in conversion from 'int' to 'char' changes value from '256' to ''[=11=]0'' [-Woverflow]
但是这个:
#include <iostream>
int main()
{
char c = 255;
std::cout << static_cast<int>(c);
}
不,但是 std::cout
在这两种情况下都不会打印 256
和 255
,所以它显示 char
can't hold [=14] =] 和 255
,但仅当 char c
为 256
?
时才会发出警告
你可以玩玩它here
在您的示例中指定 char
是否已签名很重要,但是根据您的 link 它已签名。
如果你写
char c = 256;
256
的类型为 int
,因此要将值存储在 c
中,必须转换为 char
。
对于有符号的目标类型,如果它在目标类型中是可表示的,则此类整数转换会产生相同的值。这将具有典型的位大小和有符号字符的表示形式 -128
到 127
.
如果源值在目标类型中不可表示,会发生什么情况取决于几个因素。
首先,由于 C++20 二进制补码是有保证的,这意味着结果值保证是唯一值,因此它和源值等于模 2^n
和 n
目标类型的位大小(对于 char
通常是 8
)。
在 C++20 之前,它是 实现定义的 在这种情况下会发生什么,但很可能实现只指定了与 C+ 等效的行为+20 一
因此,警告并不是为了防止未定义的行为,甚至是自 C++20 以来的实现定义的行为,而只是为了通知用户可能的错误。
我无法确定为什么 GCC 选择仅对大于 255
的值发出警告,但我的猜测是这样做是因为像
这样的语句
char c = 255;
如果您将右侧解释为 unsigned char
, 就有意义了。上面解释的转换规则不会改变转换前后表示的字符。
不过
char c = 256;
如果右侧被解释为 unsigned char
, 甚至没有意义。所以这是一个错误的可能性似乎更高。
但也许我也猜错了方向。关于 -Woverflow
警告的这种行为,GCC 有一个开放的 bug report。通过阅读那里的评论,我不清楚这种行为最初的原因是什么。
例如,Clang 始终警告所有超出范围的值。所以警告中似乎有不同的想法。
考虑这个例子:
#include <iostream>
int main()
{
char c = 256;
std::cout << static_cast<int>(c);
}
发出警告:
warning: overflow in conversion from 'int' to 'char' changes value from '256' to ''[=11=]0'' [-Woverflow]
但是这个:
#include <iostream>
int main()
{
char c = 255;
std::cout << static_cast<int>(c);
}
不,但是 std::cout
在这两种情况下都不会打印 256
和 255
,所以它显示 char
can't hold [=14] =] 和 255
,但仅当 char c
为 256
?
你可以玩玩它here
在您的示例中指定 char
是否已签名很重要,但是根据您的 link 它已签名。
如果你写
char c = 256;
256
的类型为 int
,因此要将值存储在 c
中,必须转换为 char
。
对于有符号的目标类型,如果它在目标类型中是可表示的,则此类整数转换会产生相同的值。这将具有典型的位大小和有符号字符的表示形式 -128
到 127
.
如果源值在目标类型中不可表示,会发生什么情况取决于几个因素。
首先,由于 C++20 二进制补码是有保证的,这意味着结果值保证是唯一值,因此它和源值等于模 2^n
和 n
目标类型的位大小(对于 char
通常是 8
)。
在 C++20 之前,它是 实现定义的 在这种情况下会发生什么,但很可能实现只指定了与 C+ 等效的行为+20 一
因此,警告并不是为了防止未定义的行为,甚至是自 C++20 以来的实现定义的行为,而只是为了通知用户可能的错误。
我无法确定为什么 GCC 选择仅对大于 255
的值发出警告,但我的猜测是这样做是因为像
char c = 255;
如果您将右侧解释为 unsigned char
,就有意义了。上面解释的转换规则不会改变转换前后表示的字符。
不过
char c = 256;
如果右侧被解释为 unsigned char
,甚至没有意义。所以这是一个错误的可能性似乎更高。
但也许我也猜错了方向。关于 -Woverflow
警告的这种行为,GCC 有一个开放的 bug report。通过阅读那里的评论,我不清楚这种行为最初的原因是什么。
例如,Clang 始终警告所有超出范围的值。所以警告中似乎有不同的想法。