为什么将 256 分配给 char 会引发警告,而分配 255 则不会,但两者都会导致整数溢出?

I'm*_*tor 4 c++ overflow

考虑这个例子:

#include <iostream>
int main()
{
    char c = 256;
    std::cout << static_cast<int>(c);
}
Run Code Online (Sandbox Code Playgroud)

发出警告:

warning: overflow in conversion from 'int' to 'char' changes value from '256' to ''\000'' [-Woverflow]
Run Code Online (Sandbox Code Playgroud)

但是这个:

warning: overflow in conversion from 'int' to 'char' changes value from '256' to ''\000'' [-Woverflow]
Run Code Online (Sandbox Code Playgroud)

不,但是std::cout在这两种情况下 都不会打印256and 255,因此它显示char不能保持256and ,但只有在is255时才会发出警告?char c256

你可以在这里玩弄它

use*_*522 6

指定是否char在您的示例中签名很重要,但通过您的链接它已签名。

如果你写

char c = 256;
Run Code Online (Sandbox Code Playgroud)

256具有 type int,因此必须将值存储在c转换中char

对于带符号的目标类型,如果可以在目标类型中表示,则此类整数转换会产生相同的值。典型的位大小和有符号字符的表示形式-128127

如果源值无法在目标类型中表示,会发生什么情况取决于几个因素。

首先,由于 C++20 保证了补码,这意味着结果值保证是唯一值,使得 it 和源值等于2^n目标类型(通常为)n的位大小的模。8char

在 C++20 之前,这种情况下发生的情况是由实现定义的,但实现很可能只具有与 C++20 等效的指定行为。

因此,警告并不是为了防止自 C++20 以来未定义的行为,甚至是实现定义的行为,而只是通知用户可能出现的错误。

我不确定为什么 GCC 选择仅对大于的值发出警告255,但我的猜测是这样做是因为像这样的语句

char c = 255;
Run Code Online (Sandbox Code Playgroud)

如果您将右侧解释为 则有意义unsigned char。上面解释的转换规则不会改变转换前后表示的字符。

然而

char c = 256;
Run Code Online (Sandbox Code Playgroud)

如果右侧被解释为 ,则甚至没有意义unsigned char。因此,这是一个错误的可能性似乎更高。

但也许我的猜测方向也是错误的。GCC有一个关于此警告行为的开放错误报告-Woverflow。通过阅读那里的评论,我不清楚这种行为最初的原因是什么。

例如,Clang 始终警告所有超出范围的值。因此,警告中似乎包含了不同的想法。