我写了一个测试代码,用于验证64位移植的一些问题。但我对以下情况感到困惑:
size_t size_neg_one = (size_t(-1));
int int_neg_one = -1;
printf("size_neg_one = %#zu, int_neg_one = %#x\n", size_neg_one, int_neg_one);
输出结果为:
size_neg_one = 0xffffffffffffffff
int_neg_one = 0xffffffff
显然,size_neg_one
不应该等于int_neg_one
。但我尝试了if(size_neg_one == int_neg_one)
并得到了TRUE
。它并不符合我的期望。
有人可以为我解释这个条件吗?提前谢谢。
我的DEV环境: 64位Xubuntu 13.04 gcc-4.6.3 。
答案 0 :(得分:1)
6.3.1.3有符号和无符号整数
1当整数类型的值转换为_Bool以外的另一个整数类型时,if 该值可以用新类型表示,不变 2否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内.60)
3否则,新类型已签名且值无法在其中表示;无论是 结果是实现定义的或引发实现定义的信号。
所以int
(32位2-s补码)通过将2 ^ 64加到-1来转换为size_t
(64位无符号)。
几乎每个编译器都会警告这样的比较。
答案 1 :(得分:1)
大多数二元运算符(包括==
)处理两个具有相同类型的值。如果这两种类型不同,则其中一个或两个都是提升,以便它们匹配。
规则相当复杂,但在这种情况下,int_neg_one
会提升为size_t
。这使用与用于赋予size_neg_one
值的转换完全相同的转换,因此比较会比较两个相等的值并生成true
。
答案 2 :(得分:0)
当你将size_t与INT进行比较时,其中一个会被隐式转换为另一个。
答案 3 :(得分:0)
首先,您的printf
已被破坏。它会产生未定义的行为。您使用%x
格式说明符和int
参数。 %x
需要unsigned int
参数,而不是int
参数。虽然这种组合对于非负int
值可能仍然合法,但它没有为负值定义。换句话说,您观察到的int_neg_one = 0xffffffff
输出在语言中没有特别的意义。输出显然毫无意义,因为正值0xffffffff
超出了平台上int
类型的范围。
其次,对于size_neg_one == int_neg_one
等式,正如其他已经解释过的那样,根据语言规则,比较是在无符号类型size_t
的域中执行的,这意味着您的比较实际上已被解释如
size_neg_one == size_t(int_neg_one)
右手大小与size_t(-1)
产生相同的值,这就是等式成立的原因。
答案 4 :(得分:0)
为了比较值,两个操作数必须相同
类型,由一些复杂的规则决定;在
特别是在这种情况下,size_t
是不可能的
小于int
,规则不同于它
相同尺寸或更大。然而,假设通常的情况,那里
size_t
大于或等于int
,int
将被转换为size_t
。由于size_t
得到保证
如果是整数类型,则为无符号整数类型
否定,转换的结果定义为
数学正确的结果
std::numeric_limits<size_t>::max() + 1 + int_value
。 (该
数学上正确的结果,因为在C ++中,结果
std::numeric_limits<size_t>::max() + 1
的保证是保证的
0.)