将uint32_t转换为int32_t,然后进行比较

MLa*_*paj 7 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;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,a1超出了有符号的32位整数范围,因此正如我在调试时已确认的那样,在将其强制转换后,它b1等于-1。但是,它仍然显示“等于”,而这些值显然并不相同。是什么原因造成的?

dbu*_*ush 5

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

在大多数实现你很可能会遇到,对于转换的最大值uint32_tint32_t保留位模式,并把它当作一个符号值的手段。这意味着将b1被赋值为-1。

当您与a1和比较时b1通常的算术转换适用。这些在C标准的 6.3.1.8节中有详细说明:

如果两个操作数具有相同的类型,则无需进一步转换。

否则,如果两个操作数都具有符号整数类型或都具有无符号整数类型,则将具有较小整数转换等级的操作数转换为具有较大等级的操作数的类型。

否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则将带符号整数类型的操作数转换为无符号整数类型的操作数的类型。

否则,如果带符号整数类型的操作数的类型可以表示带无符号整数类型的操作数的所有值,则带无符号整数类型的操作数将转换为带符号整数类型的操作数的类型。

否则,两个操作数都将转换为与带符号
整数类型的操作数类型相对应的无符号整数类型

高亮显示的部分适用于这种情况,因为uint32_tint32_t具有相同的排名,因此的值将b1转换为type uint32_t

在将无符号类型的超出范围的值转换时,这可以通过以下方式完成:反复对无符号类型的最大值进行数字加或减一,直到该值在范围内。这实际上意味着源值的所有多余字节都会被截断,剩下的将被视为无符号值。

C标准的 6.3.1.3节详细说明了这种转换:

1将整数类型的值转换为以外的其他整数类型时_Bool,如果该值可以用新类型表示,则该值不变。

2否则,如果新类型是无符号的,则通过在新类型可以表示的最大值之前反复加或减一,来转换值,直到该值在新类型的范围内。

3否则,将对新类型进行签名,并且无法在其中表示值;结果是实现定义的,还是引发实现定义的信号

在这种情况下,第3段适用于您第一次分配a1b1,然后第2段适用于您进行比较并b1进行转换。因此,这意味着将值-1转换为value UINT32_MAX,这就是比较结果为true的原因。