3

阅读 C++ Primer 5th edition book,我注意到signed char值为 的 a256是未定义的。我决定尝试一下,我发现这std::cout对那个 char 变量不起作用。(没有打印)。

但是在 C 上,同样的 事情signed char c = 256; 会给0.char c

我尝试搜索但没有找到任何东西。

有人可以向我解释为什么在 C++ 中会出现这种情况吗?

编辑:我知道 256 是 2 个字节,但是为什么与 C 中的不同,发生在 C++ 中?

4

6 回答 6

10

这本书大错特错。没有未定义的行为

signed char c = 256;

256是类型的整数文字int。为了用它初始化 a signed char,它被转换为signed char(§8.5 [dcl.init]/17.8;所有引用都指向 N4140)。此转换受 §4.7 [conv.integral] 的约束:

1 整数类型的纯右值可以转换为另一种整数类型的纯右值。无作用域枚举类型的纯右值可以转换为整数类型的纯右值。

2 如果目标类型是无符号的,则 [...]

3 如果目标类型是有符号的,如果它可以在目标类型(和位域宽度)中表示,则值不变; 否则,该值是实现定义的。

如果signed char不能表示 256,则转换产生一个实现定义的 type 值,signed char然后用于初始化c。这里没有什么未定义的。


当人们说“签名溢出是 UB”时,他们通常指的是 §5 [expr]/p4 中的规则:

如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。

This renders UB expressions like INT_MAX + 1 - the operands are both ints, so the result's type is also int, but the value is outside the range of representable values. This rule does not apply here, as the only expression is 256, whose type is int, and 256 is obviously in the range of representable values for int.

于 2015-02-11T12:07:55.063 回答
7

编辑:请参阅下面的 TC 答案。它更好。

signed char有符号整数溢出在 C++ 和 C 中是未定义的。在大多数实现中,, 的最大值SCHAR_MAX为 127,因此将 256 放入其中会溢出。大多数情况下,您会看到数字只是环绕(到 0),但这仍然是未定义的行为。

于 2012-11-26T17:04:54.093 回答
3

您会看到 和 之间的cout区别printf。当你输出一个字符时,cout你没有得到数字表示,你得到一个字符。在这种情况下,角色是NUL不会出现在屏幕上的。

请参阅http://ideone.com/7n6Lqc上的示例

于 2012-11-26T17:13:20.390 回答
2

char 通常是8 bits或 a byte,因此可以保存2^8不同的值。如果是unsigned, 从0255否则, 当signed-128127

于 2012-11-26T17:04:38.693 回答
1

unsigned char值是(通常是迂腐的)是从 0 到 255。有 256 个值,1 个字节可以容纳。

如果你得到溢出(通常)值使用模 256,作为其他整数类型模MAX + 1

于 2012-11-26T17:05:23.983 回答
0

@Pubby 我不知道 C/C++ 标准是否定义了有符号整数溢出时的行为,但 gcc 似乎并不总是将 (x < x + 1) 视为真的。"<" 运算符将带符号的 int 作为操作数,因此 x < x + 1 --> (int)x < (int)x + (int)1

以下代码产生输出:1 0 0 0 (32bit 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);
于 2014-02-22T13:52:05.877 回答