阅读C ++ Primer第5版的书,我注意到signed char
的值256
未定义。
我决定尝试一下,我看到std::cout
没有为char变量工作。 (没有印刷)。
但在C上,同样的事情
signed char c = 256;
会为0
提供值char c
。
我试过搜索但没有找到任何东西。
有人可以向我解释为什么C ++会出现这种情况?
编辑:我知道256是2个字节,但是为什么与C中的相同,发生在C ++中?
答案 0 :(得分:11)
这本书非常不正确。
中没有未定义的行为signed char c = 256;
256
是int
类型的整数文字。要使用它初始化signed char
,它将转换为signed char
(§8.5[dcl.init] /17.8;所有引用都转到N4140)。此转换受§4.7[conv.integral]:
1整数类型的prvalue可以转换为prvalue 另一种整数类型。可以使用无范围枚举类型的prvalue 转换为整数类型的prvalue。
2如果目的地类型是无符号的,[...]
3如果目标类型已签名,则值可以保持不变 以目的地类型(和位字段宽度)表示; 否则,该值是实现定义的。
如果signed char
不能代表256,那么转换会产生类型signed char
的实现定义值,然后用于初始化c
。这里没有什么不明确的。
当人们说“签名溢出是UB”时,他们通常是指§5[expr] / p4中的规则:
如果在评估表达式期间,结果不是 在数学上定义或不在可表示值的范围内 它的类型,行为是未定义的。
这会渲染类似INT_MAX + 1
的UB表达式 - 操作数都是int
s,因此结果的类型也是int
,但该值超出了可表示值的范围。此规则不适用于此处,因为唯一的表达式为256
,其类型为int
,而256显然位于int
的可表示值范围内。
答案 1 :(得分:6)
编辑:见T.C.的答案如下。它更好。
在C ++和C中未定义有符号整数溢出。在大多数实现中,signed char
,SCHAR_MAX
的最大值为127,因此将256放入其中会溢出它。大多数情况下,你会看到数字只是环绕(到0),但这仍然是未定义的行为。
答案 2 :(得分:3)
您看到cout
和printf
之间存在差异。输出带有cout
的字符时,如果没有数字表示,则会得到一个字符。在这种情况下,角色为NUL
,不会出现在屏幕上。
答案 3 :(得分:2)
char通常为8 bits
或byte
,因此可以保留2^8
个不同的值。如果是unsigned
,则从0
升级到255
,否则,signed
从-128
到127
答案 4 :(得分:1)
unsigned char
值(通常是迂腐的)是0到255.有256个值,1个字节可以保存。
如果出现溢出(通常),则使用模256的值作为其他整数类型的模MAX + 1
答案 5 :(得分:0)
@Pubby我不知道C / C ++标准是否在有符号整数溢出时定义了行为,但是gcc似乎并不总是将(x 以下代码生成输出:1 0 0 0(32位Linux + gcc)signed char c1, c2;
signed int i1, i2;
c1 = 127;
c2 = c1 + 1;
i1 = 2147483647;
i2 = i1 + 1;
printf("%d %d\n", c1 < c1 + 1, c1 < c2);
printf("%d %d\n", i1 < i1 + 1, i1 < i2);