将 uint32_t 转换为 int32_t 并随后比较它们

标签 c stdint

我无法理解如何比较两个 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”,而这些值显然不一样。这是什么原因造成的?

最佳答案

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

在您可能遇到的大多数实现中,将 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,这就是比较结果为 true 的原因。

关于将 uint32_t 转换为 int32_t 并随后比较它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58828063/

相关文章:

c - 如何使用 htonl 将小端转换为大端

c - 为什么我不能用两个具有相同内容的结构互换分配?

c - 与 inttypes.h、fscanf()、fprintf() 不一致

C: 将字节数组声明为 uint8_t 有什么问题吗?

c - 在C中定义16位整数

c - 通过三点A、B、C的坐标定义一个盒子

找不到段错误。在任何一种情况下都发生在第一次打印之前

c - SIGINT 被多个进程忽略

c++ - 哪个 C++ 标准头文件定义了 SIZE_MAX?

c++ - __u8 和 uint8_t 之间的区别