我正在阅读 Stroustrup 的书“C++ 编程语言第 4 版”,并且有三个关于溢出赋值的问题(特别是对有符号/无符号字符,如书中所示)。首先,根据标准5/4段:
如果在计算表达式时,结果不是
数学定义或不在可表示值的范围内
它的类型,行为未定义.
(除非目标变量是无符号的 - 在这种情况下结果是明确定义的)。但这个定义也适用于作业吗?
因为我认为书中有很多相反的说法,都在第六章。第一个与前述段落相对应,但以下评论则不然:
三者的变量char
类型可以自由分配给每个
其他。但是,为 a 指定太大的值signed char
还是
不明确的。例如:
void g(char c, signed char sc, unsigned char uc)
{
c = 255; //implementation-defined if plain chars are signed and have 8 bits
c = sc; //OK
c = uc; //implementation-defined if plain chars are signed and if uc's value is too large
sc = uc; //implementation-defined if uc's value is too large
uc = sc; //OK: conversion to unsigned
sc = c; //implementation-defined if plain chars are unsigned and if c's value is too large
uc = c; //OK: conversion to unsigned
}
第一个问题:既然分配太大的值是UB,那么为什么评论说它是实现定义的?
接下来我们有以下示例:
具体来说,假设一个char
是8位:
signed char sc = -160;
unsigned char uc = sc; //uc == 116 (because 256-160==116)
cout << uc; //print 't'
第二个问题:除了第一个作业据说是 UB 之外,作者究竟使用了什么公式来得出 116?在我的测试中,uc
得到的值为 96。
最后引用:
一个整数可以转换为另一种整数类型。如果
目的地是signed
,如果可以的话,该值不变
以目的地类型表示;否则,该值为
实现定义:
signed char sc = 1023; //implementation-defined
合理的结果是 127 和 -1。
第三个问题:再说一次,除了这与之前关于 UB 所说的相反之外,为什么可能的结果是 127 和 -1?我猜这与一个和两个补码有关,但是使用的精确公式是什么?
1)实现定义的是“一类UB”——换句话说,它仍然是UB,只是实现负责解释它是如何工作的,而不是“你根本不能依赖这个操作”。因此,如果您分配超出范围,编译器仍然可以让您的计算机爆炸char
价值观。但实现也可以定义“将其截断为 8 位等效值”。
2) 256 - 160 = 96 在我的计算器上。我敢打赌,这也是你的。也许作者有不同的计算器?或者是最后一分钟从 -150 更改为 -160 的事情之一,它忘记更改最终结果。
3)由于它是“实现定义的”,因此它最终可能几乎是任何东西。由于该值是十六进制的 0x3ff,因此我们可以将 0xff 或 0x7f 想象为合理的值,具体取决于实现决定如何执行此操作。我预计大多数编译器将使用 0xff 值。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)