天天看點

一個神奇的bug(-1真的比3小嗎?)

昨天在公司寫代碼的時候遇到一個非常神奇的bug,抽象出來就是下面這段程式:

首先聲明,這是我回到家寫的測試代碼,是以大家可以看到我使用的是MS的IDE産品,這不代表公司也是使用的這個。

大家看到這麼簡單的一段代碼是不是覺得沒什麼問題啊~!~~我也這麼覺得,可往往問題就出現在沒有問題的思想下面,大家認為if的條件判斷會成功嗎?也就是說-1是不是真的小于這個數組的元素個數呢?

首先大家不用懷疑那個計算數組個數的宏,如果認為有問題的可以自己去把ARRAY_NUM的值列印出來看,大家會發現它是3,也就是數組的個數,那麼執行這個程式後,應該是進入if,然後列印“enter”的,但是事實是這個程式沒有進入if,我在公司的時候就很納悶,這到底是為什麼呢?我列印了a的值,也确實是-1,那怎麼會-1比3大呢?我百思不得其解,回到家後,我檢視了C語言手冊,仔細分析了sizeof這個函數,最後我突然明白了是哪裡出了問題,原來sizeof()函數的傳回值是無符号數,是啊,數組的元素怎麼會是負數的,它這麼定義也沒有任何問題啊!!那到底是哪裡出了問題呢?不知道大家得知sizeof()傳回unsigned的整數時有沒有什麼啟發呢!!

對問題就出在這裡,我們大家都知道,當兩個數進行比較或者是算數運算的時候,如果兩個數的類型不一緻是會進行轉換的,相信大家在寫C語言的時候,類型轉換比我肯定背的熟,那麼,這裡a被定義成int型,當它和unsigned int相遇時,它會被轉換成什麼大家肯定比我記得清楚,對,它被轉換成了unsigned型,-1如果被轉換成unsigned型後将會是65535或者65536,這裡不去深究,反正是一個很大的整數,當然比3要大了。看到這裡有朋友肯定會覺得怎麼能這樣的,這不是坑爹嗎?對,确實很坑爹。我當時也這麼覺得,于是我果斷是查了下ANSI C的标準,發現确實存在這個問題(當然也可能是我的英文不太好,翻譯錯了),當int和unsigned int相遇時,如果int能夠完整這兩個類型的數,那麼就轉換成int,否則就轉換成unsigned。

那麼這裡果斷轉換成了unsigned,我個人喜歡K&C一些,于是我去查了下K&C裡面的内容,發覺貌似它規定的更死,一遇到unsigned就轉換成unsigned,這麼說來,不管按哪個标準來,最後的結果都是這個判斷條件失敗,看來如果想要判斷條件成功,就隻能自己手動強轉了。。。。把sizeof()的傳回值強轉成int型就可以了,這樣就不會讓a轉換成unsigned的了。。

即使手動進行強轉後程式能正常工作了,但是我相信大家和我的感覺一樣,覺得這樣太坑爹了。。。是啊!@!!但是标準庫的sizeof()函數我們是沒有辦法進行修改的,我們能修改的是我們自己的程式,我建議大家以後不要使用unsigned這個符号,完全是廢的,至少我目前還沒覺得有什麼用,甚至在進行位運算之類的時候我也可以自己去控制符号的問題,顯式出現的問題總比這種糾結的看不到的問題讓人放心,大家以後寫代碼也要小心了。不說了,該幹活了。。。