【发布时间】:2012-01-26 10:27:38
【问题描述】:
我想知道 C++ 在这种情况下的表现如何:
char variable = 127;
variable++;
在这种情况下,变量现在等于 -128。但是增量运算符是否将值包装到其下限或发生溢出?
【问题讨论】:
我想知道 C++ 在这种情况下的表现如何:
char variable = 127;
variable++;
在这种情况下,变量现在等于 -128。但是增量运算符是否将值包装到其下限或发生溢出?
【问题讨论】:
发生溢出并导致未定义的行为。
第 5.5 节:
如果在计算表达式期间,结果不是 数学定义或不在可表示值的范围内 对于它的类型,行为是未定义的[...]
该标准继续指出,在大多数实现中,整数溢出会被忽略。但这并不代表保证。
【讨论】:
普通的char 可以是有符号或无符号的。如果最大值为 127,则必须在您的实现中对其进行签名。
对于无符号类型,“溢出”定义明确,会导致回绕。对于有符号类型,算术溢出的行为是未定义的(环绕是典型的,但不是必需的)。但这实际上不适用于这种特殊情况;相反,variable 中存储的值是实现定义的。
对于比int 更窄的类型,事情会稍微复杂一些。这个:
variable ++;
等价于:
variable = variable + 1;
+ 运算符的操作数应用了“通常的算术转换”,在这种情况下,这意味着两个操作数都被提升为int。由于int 的宽度足以容纳结果,因此没有溢出;结果为128,类型为int。当该结果存储回variable 时,它会从int 转换为char。
转换的溢出规则与“+”等算术运算的溢出规则不同。对于有符号到有符号或无符号到有符号的转换,如果值不能在目标类型中表示,则行为不是未定义的;它只是产生一个实现定义的结果。
对于使用 2 的补码表示有符号整数类型的典型实现,存储的值可能是 -128 ——但其他行为也是可能的。 (例如,实现可以使用饱和算法。)
另一种(相当模糊的)可能性是char 和int 的大小可能相同(只有当char 至少为16 位时才会发生这种情况)。这可能会产生一些有趣的效果,但我不会(现在)深入讨论。
【讨论】:
unsigned char 可能与char 属于同一类型?其他整数类型也一样吗?
char、signed char 和 unsigned char 始终是不同的类型——但 char 与其中之一具有相同的表示形式。同样,int 和 long 是不同的类型,它们可能具有相同的表示形式,也可能不同,依此类推。