本節以inchar.c為例,說明從設計到調試的全過程,以便學習。
13.6.1 一個簡單的實例
【例13.11】要求將從鍵盤上輸入的一個字符按下面格式輸出,下面是一個運行示範。
Input :5 Your input is :5
這是一個順序執行過程,輸入有提示信息,輸出增加了說明。下面是含有錯誤的C語言程序,用來演示編譯和排錯的過程。
//inchar.c main ( ) { char ch ; printf (\"input :\" ); scanf (\"%d\" , ch ); printf (\"Your input is :%dn\" , ch ); }
13.6.2 編譯程序
假設工程名為myc,源程序名為inchar.c。詳細步驟不再贅述。
輸入程序,檢查輸入無誤之後,即可對程序進行編譯。這裡需要注意的一點是,初學者往往過分地依賴編譯器,不重視編譯運行之前的人工檢查。有很多的小錯誤,如拼寫錯誤等是完全可以自己檢查出來的。應當逐步培養自己的查錯能力。在編製大型軟件時,這一點顯得尤其重要。特別需要提醒的是,C語言的關鍵字在編輯窗裡是以與文字不同的顏色顯示的,如果它們也變成了相同顏色,說明這一行隱含了VC不能識別的符號。最常見的原因是混入中文不可見符號或者用中文符號代替英文符號,如中文逗號代替西文逗號。
對文件進行編譯。如圖13-1所示,操作命令已經加上所在文件的標識,所以其功能非常清楚。選擇編譯命令「Compile inchar.c」,編譯結果出現3個警告信息,如圖13-2所示。
圖13-1 工程組成信息及Build菜單
目前需要掌握的最基本的3個命令介紹如下。
(1)「Compile inchar.c」命令用來編譯文件inchar.c。如果不能通過,則不產生obj文件,並給出出錯信息。如果通過,產生inchar.obj文件,也可能給出警告信息。如果有警告信息,則說明程序有不妥之處,應該排除,直到無警告信息。需要注意的是,有警告信息時,產生的obj文件可能會有錯誤,不能產生exe文件,或者運行結果不正確。第一次調試程序時,一般都要使用這一命令檢查錯誤。編譯系統會給出出錯和警告的可能原因,這將有助於查錯。
(2)「Build myc.exe」命令在編譯文件inchar.c時,同時產生inchar.obj和myc.exe文件。如果程序有問題,又不影響產生obj文件的話,只顯示警告信息的數目,不顯示警告的內容,這是與「Compile inchar.c」命令的區別。另外,可執行文件不是以C的源程序文件名命名,而是以工程命名,所以產生的執行文件名是myc.exe,而不是inchar.exe。
(3)「Execute myc.exe」命令執行文件myc.exe。如果沒有myc.exe,則自動執行編譯程序產生myc.exe文件,然後執行myc.exe文件。
如果一開始就使用「Build myc.exe」命令,只給出有問題的信息,這時產生的執行文件可能得不到正確結果。一旦有了無錯誤信息的inchar.obj文件,就可以使用「Build myc.exe」命令產生myc.exe文件。
圖13-2 編譯信息
13.6.3 排錯
由圖13-2的警告信息可知,這個程序沒有錯誤信息,具有繼續產生執行文件的可能性。即使能產生執行文件,也能正常運行,但也應該養成排除所有警告信息的正確作風。由警告信息可以看出,程序沒有包含定義printf和scanf函數的頭文件,主函數的定義也不嚴格。假設將它改正為如下程序。
#include <stdio.h> int main ( ) { char ch ; printf (\"input :\" ); scanf (\"%d\" , &ch ); printf (\"Your input is :%dn\" , ch ); return 0 ; }
編譯正確,執行「Execute myc.exe」運行程序,如圖13-3所示,Windows彈出一個DOS窗口來運行DOS程序,按屏幕上的提示,按任意鍵即可返回開發環境。
假設輸入52,則輸出52,但輸入字符W時,程序輸出-52,證明程序不正確。所以不要只取一種情況驗證程序是否運行正確,應對各種可能的情況都進行驗證。
圖13-3 運行程序的DOS窗口及運行結果
可以啟用Debug,觀察表達式或變量的值,並設置斷點或單步運行程序。這個示例程序比較簡單,如圖13-4所示,單步運行程序,即可直接看到變量的值。如果要在右邊設置監視的變量,直接在Name欄下輸入變量名即可。
圖13-4 觀察變量在程序運行期間的變化情況
由此可見,雖然輸入字符w,但讀給變量ch的不是字符值,而是數字。scanf和printf語句的格式不對,應該改為%c。因為輸入數字,所以隱藏了這個錯誤。輸入數字時正確,輸入字符時錯誤。通過監視變量的變化情況,可以很容易地發現這是將格式符%c錯寫成格式符%d造成的。
修改後的正確程序如下:
#include <stdio.h> void main ( ) { char ch ; printf (\"input :\" ); scanf (\"%c\" , &ch ); printf (\"Your input is :%cn\" , ch ); }
由於在程序設計中錯誤總是難免的,因此調試也是必不可少的,所以應該盡快熟悉調試環境,而熟悉的唯一途徑就是多用。「實踐出真知」說的也正是這個道理。
13.6.4 基本調試命令簡介
1.設置和取消斷點
設置和取消斷點是通過選擇右鍵菜單來實現的。斷點是程序員在程序上做的標記,表示調試程序時,運行到該處應該暫停。如圖13-5所示,在要設置斷點處單擊選擇右鍵菜單命令「Insert/Remove Breakpoint」,在該行設置一個紅色圓點表示斷點。
圖13-5 設置和取消斷點示意圖
如果要取消斷點,在斷點行再次使用右鍵,則出現「Remove Breakpoint」和「Disable Breakpoint」兩個菜單命令。前一個表示將取消斷點(紅色圓點消失),後一個表示保留斷點,但暫時不起作用(程序執行時忽略這個斷點)。如果選擇後一命令,則紅色實心圓點的內部變成白色(圖13-5中的紅色圓圈),同時菜單命令變為「Enable Breakpoint」,以便將來選擇該命令恢復斷點。
可以在光標所在行直接使用F9功能鍵設置和取消斷點,也可以用它激活保留斷點,但設置保留斷點必須使用右鍵菜單。
2.調試控制
若未設置斷點,可按F10鍵(Step Over)進行調試,調試程序將停在main函數的開始處。一旦準備好程序,便可以開始調試,這時可使用其他所有功能。
可採用下述方法進行調試。
(1)一次執行一行,跳過一些函數,或單步調試所有函數。
(2)從當前位置執行到預先設立的斷點。
(3)從當前位置執行到光標所在位置。
上述方法可以選擇使用也可以混合使用。
如果對源程序作了修改,則應重新編譯,然後再進行調試。事實上,修改源程序後再用Step Over或Trace Into命令企圖再次調試時,VC將詢問用戶是否需要重新生成可執行文件。
3.調試命令和熱鍵
表13-1列出了用於調試菜單的幾個特別的調試命令和熱鍵。
表13-1 常用調試命令
4.變量窗口
在如圖13-4所示的程序窗口下面,左邊的窗口稱為變量窗口,用來顯示各個變量及其取值。變量窗口有3個選項卡,分別是「Auto」,「Locals」和「this」。我們經常要查看前兩個選項卡中的內容,這兩個選項卡的作用如表13-2所示。隨著程序的執行,如果選項卡中變量的值發生變化,則將它們用紅色顯示出來。
表13-2 變量窗口中的「Auto」與「Locals」選項卡
只要雙擊變量的值,就可以直接修改該變量的值。在調試時,可以很方便地改變變量的值,觀察它們的行為。
5.觀察窗口
在如圖13-4所示的程序窗口下面,右邊的窗口稱為觀察窗口。在變量窗口中,「Auto」和「Locals」選項卡中所顯示的變量並不是當前函數中所有有意義的變量,而且在兩個選項卡之間切換也不方便,所以常使用觀察窗口來顯示變量的值。
觀察窗口共有4個選項卡,每一個選項卡中都可以任意輸入變量。雙擊Name欄的空白處,即可輸入任意變量,其值顯示在Value欄中。雙擊變量的值,可以直接修改。
在觀察窗口中,還可以輸入一些簡單的表達式,如「y+25」,Value欄中則顯示這個表達式的值。
6.調試命令菜單
如圖13-6所示,「Bulid」菜單含有可供調試程序的子菜單。使用這些調試命令可進入程序調試狀態。
如圖13-7所示,進入調試狀態後,「Build」的位置被「Debug」菜單代替。圖13-7還給出了執行斷點行的示意圖。
圖13-6 Bulid菜單的調試命令
圖13-7 Debug菜單及執行斷點行的示意圖
13.6.5 程序與彙編調試窗口
有時需要根據彙編窗口加以觀察。下面的程序演示了內存數據的存放方式。
【例13.12】演示小端存儲的程序。
#include <stdio.h> union s{ int n ; char str[4] ; }uc ; int main ( ) { int i=0 ; uc.n=0x12345678 ; printf (\"0x%xn\" ,&uc ); for (i=0 ;i<4 ;i++ ) printf (\"0x%x 0x%xn\" ,&uc.str[i] ,uc.str[i] ); return 0 ; }
從圖13-8的窗口可以看出,uc.str[0]存儲的是0x78,對照7位ASCII編碼表,0x78也是小寫字母x的ASCII碼。對比un.n=0x12345678,str[0]裡存儲的是0x78,也就是地址0x12345678的低端地址,又稱小端地址。0x56對應大寫字符V,0x34對應數字4,而0x12則是不可顯示字符,由此證明本機是小端存儲方式。
圖13-8 演示小端地址存儲方式示意圖
可以通過圖13-8中的下拉框Context選擇顯示內容。如圖13-9所示,mainCRTStartup顯示彙編代碼。也可以直接用Windows菜單裡在c文件和Disassembly之間選擇。
圖13-10是單步運行彙編程序示意圖。
圖13-9 Windows菜單c文件和Disassembly菜單項
圖13-10 單步運行彙編程序示意圖