[英]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
。 由於沒有數字大於該值,因此循環條件永遠不會為真,並且永遠不會進入循環。
如果將其更改為 實際上,在這種情況下,您可能不應該使用 unsigned :-)i >= 0
,那應該可以按預期工作。
無論您處理的是無符號數還是有符號數,-1 都將始終編譯為 0xffffffff。 處理器具有有符號和無符號比較標志。 當將該數字與 5 進行比較時,有符號標志會將其視為 -1 並表示它較小,但無符號標志會將其視為一個大數並表示它較大。 由於該數字也與 UINT_MAX 相同,因此對於所有無符號數字,您的比較都是錯誤的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.