考虑以下†:
size_t r = 0;
r--;
const bool result = (r == -1);
结果初始化 result
的比较是否具有明确定义的行为?
它的结果 true
是否如我所料?
写这个问答是因为我特别不确定两个因素。
在我的回答中,它们都可以通过使用“关键[ly]”一词来识别。
† 这个例子的灵感来自于计数器无符号时循环条件的方法:
for (size_t r = m.size() - 1; r != -1; r--)
最佳答案
size_t r = 0;
r--;
const bool result = (r == -1);
严格来说,result
的值是实现定义的。在实践中,几乎可以肯定是 true
;如果有一个实现是 false
,我会感到惊讶。 .
r
的值在 r--
之后是 SIZE_MAX
的值, <stddef.h>
中定义的宏/<cstddef>
.
比较r == -1
,通常的算术转换在两个操作数上执行。通常算术转换的第一步是将积分提升应用于两个操作数。
r
是 size_t
类型,实现定义的无符号整数类型。 -1
是 int
类型的表达式.
在大多数系统上,size_t
至少与 int
一样宽.在这样的系统上,积分提升会导致 r
的值。要么转换为unsigned int
或保留其现有类型(如果 size_t
具有与 int
相同的宽度,但转换等级较低,则前者可能发生)。现在左操作数(无符号)至少具有右操作数(有符号)的等级。右操作数转换为左操作数的类型。此转换产生与 r
相同的值,因此相等比较产生 true
.
这是“正常”情况。
假设我们有一个实现,其中 size_t
是 16 位(假设它是 typedef
的 unsigned short
)和 int
是 32 位。所以SIZE_MAX == 65535
和 INT_MAX == 2147483647
.或者我们可以有一个 32 位的 size_t
和一个 64 位 int
.我怀疑是否存在任何此类实现,但标准中没有任何内容禁止它(见下文)。
现在比较左侧的类型为 size_t
和值(value)65535
.自签名 int
可以表示 size_t
类型的所有值,积分促销将值转换为 65535
类型为 int
。两侧==
运算符的类型为 int
,所以通常的算术转换无关。该表达式等价于 65535 == -1
,这显然是 false
.
正如我所提到的,这种情况不太可能发生在 size_t
类型的表达式中。 - 但它很容易发生在较窄的无符号类型上。例如,如果 r
被声明为 unsigned short
, 或 unsigned char
,甚至是普通的 char
在对该类型进行签名的系统上,result
的值可能是false
. (我说可能是因为 short
甚至 unsigned char
可以具有与 int
相同的宽度,在这种情况下 result
将是 true
。)
在实践中,您可以通过显式进行转换而不是依赖实现定义的常用算术转换来避免潜在问题:
const bool result = (r == (size_t)-1);
或
const bool result = (r == SIZE_MAX);
C++11 标准引用:
- 5.10 [expr.eq] 等式运算符
- 5.9 [expr.rel] 关系运算符(指定执行通常的算术转换)
- 5 [expr] 表达式,第 9 段:常用算术转换
- 4.5 [conv.prom] 整体促销
- 18.2 [support.types]
size_t
18.2 第 6-7 段:
6 The type
size_t
is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object.7 [ Note: It is recommended that implementations choose types for
ptrdiff_t
andsize_t
whose integer conversion ranks (4.13) are no greater than that ofsigned long int
unless a larger size is necessary to contain all the possible values. — end note ]
所以没有禁止制作size_t
比 int
窄.我可以几乎合理地想象一个系统,其中 int
是 64 位,但没有单个对象可以大于 232-1 个字节,所以 size_t
是 32 位。
关于c++ - 是否将下溢的无符号整数与 -1 进行了明确的比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27405418/