程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> Bug分析之0減1到底等於幾

Bug分析之0減1到底等於幾

編輯:.NET實例教程
0減1等於幾?小學生都知道,而計算機卻常干傻事。本文介紹一種和數據類型相關的編程Bug,分析Bug現象和產生原理,做為小小的Debug經驗與大家分享。 

 


前幾天用VC寫了個程序,程序中有個遍歷列表的功能。使用vector作為列表的數據結構,用一個整型數CurIndex記錄當前記錄。當用戶點擊向前按鈕時,CurIndex減1,如果CurIndex已經是第一個元素了,就讓CurIndex轉向最後一個元素。
 
變量聲明如下:
 

vector<ItemType> Vector;
int CurIndex;
 
在用戶點擊向前按鈕時,調用下面的函數:


void MovePre()
{
       --CurIndex;
       if (CurIndex<0)
              CurIndex = Vector.size()-1;
}

 
這段程序有個問題:當Vector為空是,Vector.size()為0,這時界面顯示CurIndex為-1。為了避免CurIndex為-1,把 MovePre的代碼改為如下:      


void MovePre()
{
       --CurIndex;
       if$False$

0);"> (CurIndex<0)
              CurIndex = max(0, Vector.size()-1); // 這裡使用max宏
}

 
按預期,當Vector為空時,CurIndex的值應該為0。然而實際結果是CurIndex仍然為-1。單步調試,的確執行了相應的語句,但CurIndex的就是不變的-1,重新編譯也沒用。這是不是很奇怪呢?
 
如果Vector.size()-1的結果小於0,那麼max(0, Vector.size()-1)的結果就應該是0;
 
如果Vector.size()-1的結果比0大,那麼max(0, Vector.size()-1)的結果就應該是個正整數才對。
 
然而實際結果確是-1。0減1比0大,並且等於-1?多麼矛盾呀!
 
如果您看了下面的語句,也許就矛塞頓開了:


int CurIndex = max( 0, (unsigned int)0-1);
 
您認為CurIndex應該等於幾呢?
 
當0減去1的時候,它的結果化為16進制,應該為0x ff ff ff ff(假設為4字節)。作為有符號整數,它的值為-1。而做為無符號整數,它的值為4294967295(使用Windows自帶的計算器算的)。
 
按C++的隱式類型轉換規則:程序在執行算術運算時,低類型向高類型轉換。這時(unsigned int)0-1的值為4294967295。顯然這個值比0大,所以max( 0, (unsigned int)0-1)的計算結果應該為4294967295,即0x ff ff ff ff,類型為無符號整型(unsigned int)。
 
當把這個結果賦值給CurIndex時,CurIndex是int型的,使用另一條C++的隱式類型轉換規則:在賦值表達式中,右邊表達式的值自動隱式轉換為左邊變量的類型,並賦值給它。0x ff ff ff ff當做整型賦值,結果就是-1。所以CurIndex的值為-1,16進制仍然是0x ff ff ff ff。
 
vect類的size()函數返回值就是無符號型的,所以CurIndex = max(0, Vector.size()-1)的值可能為-1就不奇怪了。
 
所以0減1等於幾,還得看是什麼類型的0,以及什麼類型的1。
 
0-1 == -1;
(unsigned int)0-1 == 4294967295;
 
Bug一不小心就跑出來,借用范廚師的話:真是防不勝防呀!
 
作者:蘇林 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved