簡體   English   中英

將 uint32_t 轉換為 int32_t 並在之后進行比較

[英]Casting uint32_t to int32_t and comparing them afterwards

我無法理解如何比較兩個整數,其中一個是 unsigned int32 而另一個是有符號 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 位 integer 范圍,所以正如我在調試時確認的那樣,在它被轉換后, b1等於-1 但是它仍然打印“Equal”,而這些值顯然不一樣。 它是由什么引起的?

正如您所做的那樣,到有符號 integer 類型的超出范圍轉換是實現定義的。

在您可能遇到的大多數實現中,將uint32_t的最大值轉換為int32_t意味着保留位模式並將其視為有符號值。 這意味着b1被賦值為 -1。

然后,當您比較a1b1時,將應用通常的算術轉換 這些在C 標准的第 6.3.1.8 節中有詳細說明:

如果兩個操作數具有相同的類型,則不需要進一步轉換。

否則,如果兩個操作數都具有帶符號的 integer 類型或都具有無符號的 integer 類型,則將具有較小 Z157DB7DF530023575 類型的操作數轉換為具有較高轉換等級的類型。

否則,如果具有無符號 integer 類型的操作數的秩大於或等於另一個操作數類型的秩,則將具有符號 integer 類型的操作數轉換為具有無符號 Z15727DB7DF53600923 類型的操作數的類型。

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.

否則,兩個操作數都轉換為無符號數
integer 類型對應帶符號的操作數類型 integer 類型

突出顯示的部分適用於這種情況,因為uint32_tint32_t具有相同的等級,所以b1的值被轉換為類型uint32_t

當為無符號類型轉換超出范圍的值時,這是通過在數值上重復地增加或減去無符號類型的最大值,直到該值在范圍內。 這實際上意味着源值的任何多余字節都將被截斷,剩下的將被視為無符號值。

C 標准的第 6.3.1.3 節詳細說明了這種轉換:

1當一個具有 integer 類型的值轉換為另一個 integer 類型而不是_Bool時,如果該值可以用新類型表示,則它是不變的。

2否則,如果新類型是無符號的,則在新類型可以表示的最大值的基礎上反復加減一,直到值在新類型的范圍內。

3否則,新類型是有符號的,值不能在其中表示; 結果是實現定義的或引發了實現定義的信號

在這種情況下,第 3 段適用於您首先將a1分配給b1時,然后第 2 段適用於您進行比較並轉換b1時。 這意味着值 -1 被轉換為值UINT32_MAX ,這就是比較結果為真的原因。

內置==只能比較相同類型的值。 如果操作數的類型不同,則預先將它們轉換為相同的類型。 (有關如何選擇此類型,請參閱cppreference 。)

在這種情況下,在執行比較之前將b1轉換為uint32_t

一般來說,無符號到有符號的轉換現在是實現定義的( 6.3.1.3 )(這可能會在 C 標准的未來版本中發生變化)。

在實踐中,整數將是二進制補碼,並且任一方向的轉換都是無操作的——相同的數據將根據二進制補碼算法的工作方式進行不同的解釋。

在您的情況下,相等是由於通常的算術轉換 (6.3.1.8)在比較中將帶符號的b1在語義上轉換為a1的無符號類型引起的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM