在询问比较是基于值还是位模式之前,你已经得出了结论,因为有一个重要的步骤。在比较之前,
==
的操作数会被转换为一个共同的类型。
例如,在比较一个32位二进制补码的
int x
和位模式1000…0000
2(表示 −2,147,483,648)以及一个带有相同位模式(表示 +2,147,483,648)的
unsigned int y
时,如果用
x == y
进行比较,则
x
首先转换为
unsigned int
,此时结果为+2,147,483,648。然后将+2,147,483,648与+2,147,483,648进行比较,所以
==
则报告它们相等。
根据 C 2018 6.5.9 (“Equality operators”) 4 的规定:
如果操作数都是算术类型,执行常规算术转换……
常规算术转换在6.3.1.8中以如下方式描述: 众多期望算术类型操作数的运算符会以类似方式执行转换并产生类似结果类型。目的是确定操作数和结果的公共实际类型。对于指定的操作数,每个操作数都将被转换……到与其对应实际类型相同的类型。
规则涉及一些技术细节,但在很大程度上,当你比较两个整数类型时,首先会将每个类型提升至至少为
int
,然后将较窄的类型转换为较宽的类型。如果它们是相同宽度但一个是无符号的,则有符号类型将被转换为无符号类型。这可能会改变值。
确定要比较的实际值后,
==
的结果将基于这些值而不是位模式来定义。
(最常见的区别情况是带有浮点 +0 和 −0 的情况,它们表示相同的实数且比较相等但具有不同的表示。在大多数现代环境中,整数类型中的所有位模式表示不同的值,并且二进制浮点类型中的所有位模式代表不同的值或 NaN,除了+0和−0之外。有一些使用较少的浮点类型对某些值具有多个表示方式,类似于3.5•10
7和35•10
6表示相同的数字。)
如果您比较带符号整型中的负值(经过推广后)与宽度相同或更宽的无符号类型,则在比较之前将更改有符号类型的值。因此,您有一定风险得到“数学上错误”的结果。