我==对 C中运算符的确切含义有点困惑。
它是比较变量代表的数学值(取决于它们的类型)还是变量背后的位模式?具体来说:
int x = 0x80000000;
unsigned y = x;
x==y // true
Run Code Online (Sandbox Code Playgroud)
因此,尽管 x 是一个很大的负值而 y 是一个很大的正值,但它们是相等的(我猜是因为它们具有相同的位模式)。
int64_t x = 0x8000000000000000;
int y = x;
x==y // false
Run Code Online (Sandbox Code Playgroud)
这里 x 和 y 中的第一个(最低有效)32 位是否相同并不重要。因此,在这种情况下,C 看起来像是在查看变量表示的值。
官方规则是什么,是否有权威参考(在 K&R 中没有发现任何有用的信息)?
我gcc在上面的例子中使用了编译器。
在询问比较是基于值还是位模式时,您已经得出结论,因为首先有一个重要的步骤。在比较之前,将 的操作数==转换为通用类型。
例如,当您将 32 位二进制补码int x与位模式 1000…0000 2(表示 ?2,147,483,648)和unsigned int y具有相同位模式(表示 +2,147,483,648)的 比较时x == y,x首先转换为unsigned int,产生 +2,147,483,647 . 然后将 +2,147,483,648 与 +2,147,483,648 进行比较,因此==报告它们相等。
C 2018 6.5.9(“平等运算符”)4 说:
如果两个操作数都是算术类型,则执行通常的算术转换……
在通常的算术转换在6.3.1.8规定。第 1 段开始:
许多期望算术类型操作数的运算符会以类似的方式导致转换并产生结果类型。目的是确定操作数和结果的通用实数类型。对于指定的操作数,每个操作数都被转换……为一个类型,其对应的实数类型是公共实数类型。
规则涉及一些技术细节,但是,在很大程度上,当您比较两个整数类型时,首先每个类型将至少提升为int,然后将较窄的类型转换为较宽的类型。如果它们的宽度相同但一个是无符号的,则有符号类型将转换为无符号类型。这可能会更改该值。
一旦确定了要比较的实际值==,就根据值而不是位模式来定义结果。
(它们不同的最常见情况是浮点 +0 和 ?0,它们表示相同的实数并且比较相等但具有不同的表示形式。在大多数现代环境中,整数类型中的所有位模式表示不同的值,并且二进制浮点类型中的所有位模式表示不同的值或 NaN,除了 +0 和 ?0。有一些不太常用的浮点类型对某些值有多种表示,类似于方式 3.5•10 7和 35•10 6代表相同的数字。)
任何时候将有符号整数类型中的负值与宽度相同或更宽的无符号类型进行比较(提升后),有符号类型的值将在比较之前更改。所以你有得到“数学错误”结果的风险。