2016-01-29 167 views
3

我遇到了我寫的程序有問題。該程序將進入if語句,而不應該。 我有兩個變量:比較C中的負數

size_t len = 5; 
int tmp = -1; 

當我做!。

if (tmp > len) 
    ft_putstr("this is crazy"); 

我打印出「這太瘋狂了,而-1小於5我 好吧,好吧,所以我看着我最喜歡的網站,看到this

當嘗試:

printf("%zu", tmp) 

我看到一個很大的正數。好 !這可能是爲什麼我的程序進入if條件的原因,但我怎麼能使它不進入if條件?謝謝

+4

這是因爲'size_t'是一個無符號整數類型,所以當比較一個有符號整數類型時,就會執行無符號比較。 –

+1

嘗試'if(tmp> 0 && tmp> len)' – user3386109

+0

'printf(「%zu」,tmp);'會導致未定義的行爲。使用'printf',您可以使用正確的格式說明符。 –

回答

0

你必須瞭解不同變量類型之間的區別。變量類型如int,unsigned,size_t等有不同的行爲,並基於你得到的結果。

如果你真的想比較兩個數字,他們都必須在同一水平(變量類型),否則你會得到意想不到的結果。

以下將解決您的問題。

if(tmp > (int)len) 
    ft_putstr("this is crazy"); 

由於@jblixr建議(對於評論的感謝),你可能要採取sizeof這些變量類型的照顧,並確保當從一種數據類型轉換值到另一種數據類型的值不被丟失。

+3

你認爲這是一個很好的解決方案啊?如果'len'與'4294967295'類似,會發生什麼?那麼'len'將被視爲負數。 –

+0

@jblixr如果您指的是sizeof'size_t'和'int';沒有。 – Pawan

+1

「size_t」值大於「INT_MAX」的可能性有多大?不是特別的。這種比較在大多數情況下都很好。 –

5

這裏的問題是,你正試圖比較一些未簽名的東西和已簽名的東西。這意味着在實際轉換完成之前有一個隱式轉換。在這種情況下,signed被轉換爲unsigned(這通常不是人們想要的 - 因此許多編譯器可以選擇在完成時顯示警告)。

要做到這一點你會寫一個草率的方式比較正確:

if((int)tmp > (int)len) 

但是這忽略了一個事實size_t可以有一個是int值過大。嚴格來說,必須處理intsize_t的範圍相結合的範圍可以大於任何可用的類型。這意味着你將不得不在兩種情況下處理這個問題,所以你會使用這個事實,即如果tmp<0那麼tmp<len(數學上,因爲len>=0)。因此,例如在數學上tmp<len將被寫爲tmp<0 || tmp<len。而相反的是tmp>=0 && tmp >= len。因此,你應該寫:

if(tmp >= 0 && tmp > len) 

注意,則轉換是沒有問題的,tmp可以在第一次檢查後轉換爲無無值改變,intsize_t不同範圍也不是問題作爲比較之前,較小者轉換爲較寬範圍。

剩下的唯一問題是,如果您啓用了關於帶符號無符號比較的警告(以檢測這些類型的錯誤),它仍會警告。爲了照顧到這一點,您需要明確地輸入它,但是我們知道一旦我們檢查了tmp>=0,轉換爲無符號不會改變tmp。因此,爲了避免警告你可以這樣寫:

if(tmp >= 0 && (unsigned)tmp > len)) 

(unsigned)是因爲tmpint,你需要轉換爲無符號時,如果tmp是另一種類型的尊重類型。