簡體   English   中英

為什么 C 不運行 unsigned int 與負值的比較?

[英]Why does C not run a comparison of unsigned int with negative value?

考慮這個 C 代碼:

#include "stdio.h"

int main(void) {

    int count = 5;
    unsigned int i;

    for (i = count; i > -1; i--) {
        printf("%d\n", i);
    }
    return 0;
}

我的觀察/問題:循環永遠不會被執行。 但是如果我將 i 的數據類型從 unsigned int 更改為 int,一切都會按預期工作。

當您嘗試不斷減去它們時,我一直將無符號整數視為“環繞”的值。 因此,當 i 為零並減去 1 時,它將環繞到 UINT_MAX。 而且由於它的值永遠不會是負數,這實際上是一個無限循環。 (這正是我將比較從 i > -1 更改為 i >= 0 時發生的情況。)

我的邏輯中有一個錯誤,因為如果 i 是無符號的,則循環永遠不會被執行,我將它與 -1 進行比較。 編譯器會以某種方式對其進行優化,或者運行時值的行為與我的預期不同。

為什么循環不運行?

i > -1中,-1 被轉換為unsigned int ,從而產生值UINT_MAX i永遠不會大於該值,因此循環體永遠不會執行。

您可能會發現您可以說服編譯器警告您:在條件上下文中使用始終為真或始終為假的表達式。 但是,如果您編寫了i > -2 ,那仍然無濟於事,因此您可能還會發現您可以為所有混合符號比較啟用警告。

請注意,在 C 中,始終使用相同類型的操作數執行算術運算。 這包括比較,但 IIRC 不包括移位運算符。 如果操作數的類型不同,如本例所示,則至少將其中一個轉換為相同類型。 計算目標類型的規則在 6.3.1.1/2 和 6.3.1.8/1 中。

當您在“類型對稱”二元運算(如您的示例中的+*> )中混合相同寬度的有符號和無符號操作數時,無符號類型“獲勝”並且該操作在無符號域中進行評估。 即有符號操作數被轉換為無符號類型。

在您的示例中, integer 常量的類型為signed int ,而i的類型為unsigned int 操作數具有相同的寬度,因此在您的示例中i > -1被解釋為i > (unsigned) -1 ,相當於i > UINT_MAX 這就是為什么您的循環永遠不會執行的原因。

-1 在無符號比較中變為UINT_MAX 由於沒有數字大於該值,因此循環條件永遠不會為真,並且永遠不會進入循環。

如果將其更改為i >= 0 ,那應該可以按預期工作。 實際上,在這種情況下,您可能不應該使用 unsigned :-)

無論您處理的是無符號數還是有符號數,-1 都將始終編譯為 0xffffffff。 處理器具有有符號和無符號比較標志。 當將該數字與 5 進行比較時,有符號標志會將其視為 -1 並表示它較小,但無符號標志會將其視為一個大數並表示它較大。 由於該數字也與 UINT_MAX 相同,因此對於所有無符號數字,您的比較都是錯誤的。

暫無
暫無

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

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