将 uint32_t 转换为 int32_t 并在之后进行比较

Casting uint32_t to int32_t and comparing them afterwards

我无法理解如何比较两个 int,其中一个是 unsigned int32,另一个是 signed int32。 让我们考虑这个简单的程序:

#include <stdint.h>

int main()
{
    uint32_t a1 = UINT32_MAX;
    int32_t b1 = (int32_t)a1;

    if (a1 == b1)
        printf("Equal");
    else
        printf("Not equal");

    return 0;
}

在这种情况下,a1 超出了带符号的 32 位整数范围,所以正如我在调试时确认的那样,在转换后,b1 等于 -1。 但是它仍然打印 "Equal",而这些值显然不一样。它是由什么引起的?

内置函数==只能比较相同类型的值。如果操作数的类型不同,则预先将它们转换为相同的类型。 (有关如何选择此类型,请参阅 cppreference。)

在这种情况下,b1 在执行比较之前转换为 uint32_t

一般来说,无符号到有符号的转换是实现定义的 (6.3.1.3) 截至目前(这可能会在 C 标准的未来版本中改变)。

实际上,整数将是二进制补码,任何方向的转换都将是空操作 — 相同的数据将根据二进制补码算法的工作方式进行不同的解释。

你的例子中的相等性是由于 usual arithmetic conversions (6.3.1.8) 在比较中有符号 b1 在语义上转换为 a1 的无符号类型引起的。

正如您所做的那样,超出范围的有符号整数类型转换是实现定义的

在您可能遇到的大多数实现中,将 uint32_t 的最大值转换为 int32_t 意味着保留位模式并将其视为有符号值。这意味着 b1 被分配了值 -1。

当您随后比较 a1b1 时,通常的算术转换 适用。这些在 C standard:

的第 6.3.1.8 节中有详细说明

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned
integer type corresponding to the type of the operand with signed integer type

突出显示的部分适用于这种情况,因为 uint32_tint32_t 具有相同的等级,因此 b1 的值转换为类型 uint32_t .

当为无符号类型转换超出范围的值时,这是通过在无符号类型的最大值上重复加或减一直到该值在范围内来实现的。这实际上意味着源值的任何多余字节都将被截断,剩下的将被视为无符号值。

此转换在 C standard 的第 6.3.1.3 节中有详细说明:

1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised

在这种情况下,当您首先将 a1 分配给 b1 时,第 3 段适用,然后当您进行比较并转换 b1 时,第 2 段适用。所以这意味着值 -1 被转换为值 UINT32_MAX,这就是比较结果为真的原因。