『壹』 c語言怎麼一步一步調試
C語言的調試步驟如下:
在keil中調試c語言程序:1、打開我們的程序,點擊菜單欄右側的start/stopdebug..按鈕,進入調試模式。2、左側為寄存器窗口,右上方是匯編窗口,我們可以看到各個寄存器的數值和c語言對應的匯編代碼。3、點擊單步執行按鈕或者點擊f11、f10,都可以進入單步執行模式,方便我們看程序流程和執行步驟。4、點擊菜單欄的串口按鈕,我們來調試串口的輸出,這里有很多對應的調試工具可供選擇。5、單步執行,我們看到各個窗口的變化,當直行到輸出時,可以看到串口窗口有相應的字元輸出。6、再次點擊start/stop按鈕來停止調試。
用vs2012對C語言進行調試:1、要對編程環境左邊的一條豎直的空開的地方進行點友租擊,點擊的是你要調試的相應的語句。2、點擊窗口上方的工具欄的調試界面,點擊逐語句或逐過程,都沒關系。3、開始調試,在調試過程中每個調試語句都要按一次F5鍵,在鍵盤做賣上按下,你可以看到執行的當前的語句中,左邊位置的紅點有個箭頭。4、在每次調試語句中,變數值發生改變時,下方的小界面都會顯示出來,看是否正確。5、不斷地重復這個步驟好胡兆,知道發現錯誤的地方為止。6、發現錯誤後,停止調試,修改相應的代碼,即完成此次調試。
『貳』 c語言程序調試
調試程序一般應經過以下幾個步驟:
1先進行人工檢查,即靜態檢查。在寫好一個程序以後,不要匆匆忙忙上機,而應對紙面上的程序進行人工檢查。這一步是十分重要的,它能發現程序設計人員由於疏忽而造成的多數錯誤。而這一步驟往往容易被人忽視。有人總希望把一切推給計算機系統去做,但這樣就會多佔用機器時間,作為一個程序人員應當養成嚴謹的科學作風,每一步都要嚴格把關,不把問題留給後面的程序。
為了更有效地進行人工檢查,所編的程序應注意力求做到以下幾點:應當採用結構化程序方法編程,以增加可讀性;2盡可能多加註釋,以幫助理解每段程序的作用;3在編寫復雜的程序時不要將全部語句都寫在main函數中,而要多利用函數,用一個函數來實現一個單獨的功能。這樣既易於閱讀也便於調試,各函數之間除用參數傳遞數據這一渠道以外,數據間盡量少出現耦合關系,便於分別檢查和處理。
2在人工檢查無誤後,才可以上機調試。通過上機發現錯誤稱動態檢查。在編譯時給出語法錯誤的信息,可以根據提示的信息具體找出程序中出錯之處並改正之。應當注意的是有時提示的出錯並不是真正出錯的行,如果在提示出錯的行上找不到錯誤的話應當到上一行再找。有時提示出錯的類型並非絕對准確,由於出錯的情況繁多各種錯誤互有關聯,因止要善於分析,找出真正的錯誤,而不要只從字面意義上找出錯信息,鑽牛角尖。
如果系統提示的出錯信息多,應當從上到下一一改正。有時顯示出一大片出錯信息往往使人感到問題嚴重,無從下手。其實可能只有一二個錯誤。例如,對使用的變數未定義,編譯時就會對所有含該變數的語句發出出錯信息;有的是少了「}」或多了「}」有的是書寫語句時忘記寫「;」或是全形的「;」了,只要加上一個變數定義,或填加「};」就所有錯誤都消除了。
3在改正語法錯誤後,程序經過連接就得到可執行的目標程序。運行程序,輸入程序所需數據,就可得到運行結果。應當對運行結果作分析。看它是否符合要求。有的初學者看到運行結果就認為沒問題了,不作認真分析,這是危險的。
有時,數據比較復雜,難以立即判斷結果是否正確。可以事先考慮好一批「試驗數據」,輸入這些數據可以得出容易判斷正確與否的結果。可以在計算的輸出結果的程序地方加入一段輸出到串口的程序,利用串口窗口可以方便看到結果的,比模擬的都好和直觀。例如,if語句有兩個分支,有可能在流程經過其中一個分支時結果正確,而經過其它一個分支時結果不對等。必須考慮周全。
事實上,當程序復雜時很難把所有的可能方案全部都試到,選擇典型的情況作試驗即可。
4 運行結果不對,大多屬於邏輯錯誤。對這類錯誤往往需要仔細檢查和分析才能發現。可以採用以下辦法:
1 將程序與流程圖仔細對照,如果流程圖是正確的話,程序寫錯了,是很容易發現的。例如,復合語句忘記寫花括弧,只要一對照流程圖就能很快發現。
2 如果實在找不到錯誤,可以採用「分段檢查」的方法。在程序不同的位置設幾個printf函數語句,輸出有關變數的值,往下檢查。直到找到在哪一段中數據不對為止。這時就已經把錯誤局限在這一段中了。不斷減小「查錯區」,就可能發現錯誤所在。
3 也可以用「條件編譯」命令進行程序調試(在程序調試階段,若干printf函數語句就要進行編譯並執行。當調試完畢,這些語句不要再編譯了,也不再被執行了)。這種方法可以不必一一去printf函數語句,以提高效率。
4 如果在程序中沒有發現問題,就要檢查流程圖有無錯誤,即演算法有無問題,如有則改正之,接著修改程序。
5 有的系統還提供debug(調試)工具,跟蹤流程並給出相應信息,使用更為方便,如KEILC51里的調試運行就很好用的,可以在命令的窗口輸入程序中需要的數據和開關量、中斷、I/O口的電平等來方便完成程序的運行,使用時要先打開Options for Target'Target1'(工程菜單里的目標『TARGET1'屬性)-----點DEBUG----選中左邊use Simulator\load Application at sta\Go till main;按確定後退出到編輯畫面,要先對源程序進行編譯後沒有錯誤才可以按主菜單上的調試按鈕,進行調試的,F10為子程序運行式的單步、F11為單步調試;具體使用可以看本站提供的51單片機應用系統開發實例一書中的Dscope foe Windows一節。可以下載本站上中文版的KIELC51就直觀了。
總之,程序調試是一項細致深入的工作,需要下功夫,動腦子,善於累積經驗。在程序調試過程中往往反映出一個人的水平,經驗和科學態度。希望讀者能給以足夠的重視。上機調試程序的目的決不 是為了「驗證程序的正確」,而是「掌握調試的方法和技術」,不要一直依賴模擬器來解決,要學會自己找問題,這樣慢慢自己就會寫出錯誤較少的實用的程序,站長就沒有模擬器的哦,靠KEILC51里的軟體模擬就解決了。
請採納。
『叄』 對C語言進行調試的最好方法是什麼
要了解調試程序的最好方法,首先要分析一下調試過程的三個要素:
應該用什麼工具調試一個程序?
用什麼辦法才能找出程序中的錯誤?
怎樣才能從一開始就避免錯誤?
應該用什麼工具調試一個程序?
有經驗的程序員會使用許多工具來幫助調試程序,包括一組調試程序和一些"lint」程序,當然,編譯程序本身也是一種調試工具。
在檢查程序中的邏輯錯誤時,調試程序是特別有用的,因此許多程序員都把調試程序作為基本的調試工具。一般來說,調試程序能幫助程序員完成以下工作:
(1)觀察程序的運行情況
僅這項功能就使一個典型的調試程序具備了不可估量的價值。即使你花了幾個月的時間精心編寫了一個程序,你也不一定完全清楚這個程序每一步的運行情況。如果程序員忘記了某些if語句、函數調用或分支程序,可能會導致某些程序段被跳過或執行,而這種結果並不是程序員所期望的。不管怎樣,在程序的執行過程中,尤其是當程序有異常表現時,如果程序員能隨時查看當前被執行的是那幾行代碼,那麼他就能很好地了解程序正在做什麼以及錯誤發生在什麼地方。
(2)設置斷點
通過設置斷點可以使程序在執行到某一點時暫時停住。當你知道錯誤發生在程序的哪一部分時,這種方法是特別有用的。你可以把斷點設置在有問題的程序段的前面、中間或後面。當程序執行到斷點時,就會暫時停住,此時你可以檢查所有局部變數、參數和全局變數的值。如果一切正常,可以繼續執行程序,直到遇到另一個斷點,或者直到引起問題的原因暴露出來。
(3)設置監視
程序員可以通過調試程序監視一個變數,即連續地監視一個變數的值或內容。如果你清楚一個變數的取值范圍或有效內容,那麼通過這種方法就能很快地找出錯誤的原因。此外,你可以讓調試程序替你監視變數,並且在某個變數超出預先定義的取值范圍或某個條件滿足時使程序暫停執行。如果你知道變數的所有行為,那麼這么做是很方便的。
好的調試程序通常還提供一些其它功能來簡化調試工作。然而,調試程序並不是唯一的調試工具,lint程序和編譯程序本身也能提供很有價值的手段來分析程序的運行情況。
注意:lint程序能分辨數百種常見的編程錯誤,並且能報告這些錯誤發生在程序的哪一部分。盡管其中有一些並不是真正的錯誤,但大部分還是有價值的。
lint程序和編譯程序所提供的一種典型功能是編譯時檢查(compile—time checks),這種功能是調試程序所不具備的。當用這些工具編譯你的程序時,它們會找出程序中有問題的程序段,可能產生意想不到的效果的程序段,以及常見的錯誤。下面將分析幾個這種檢查方式的應用例子,相信對你會有所幫助。
等於運算符的誤用
編譯時檢查有助於發現等於運算符的誤用。請看下述程序段:
void foo(int a,int b)
{
if ( a = b )
{
/ * some code here * /
}
}
這種類型的錯誤一般很難發現!程序並沒有比較兩個變數,而是把b的值賦給了a,並且在b不為零的條件下執行if體。一般來說,這並不是程序員所希望的(盡管有可能)。這樣一來,不僅有關的程序段將被執行錯誤的次數,並且在以後用到變數a時其值也是錯誤的。
未初始化的變數
編譯時檢查有助於發現未初始化的變數。請看下面的函數:
void average ( float ar[], int size )
{
float total;
int a;
for( a = 0;a<size; ++a)
{
total+=ar[a];
}
printf(" %f\n", total / (float) size );
}
這里的問題是變數total沒有被初始化,因此它很可能是一個隨機的無用的數。數組所有元素的值的和將與這個隨機數的值相加(這部分程序是正確的),然後輸出包括這個隨機數在內的一組數的平均值。
變數的隱式類型轉換
在有些情況下,C語言會自動將一種類型的變數轉換為另一種類型。這可能是一件好事(程序員不用再做這項工作),但是也可能會產生意想不到的效果。把指針類型隱式轉換成整型恐怕是最糟糕的隱式類型轉換。
void sort( int ar[],int size )
{
/* code to sort goes here * /
}
int main()
{
int arrgy[10];
sort( 10, array );
}
上述程序顯然不是程序員所期望的,雖然它的實際運行結果難以預測,但無疑是災難性的。
用什麼辦法才能找出程序中的錯誤?
在調試程序的過程中,程序員應該記住以下幾種技巧:
先調試程序中較小的組成部分,然後調試較大的組成部分
如果你的程序編寫得很好,那麼它將包含一些較小的組成部分,最好先證實程序的這些部分是正確的。盡管程序中的錯誤並不一定發生在這些部分中,但是先調試它們有助於你理解程序的總體結構,並且證實程序的哪些部分不存在錯誤。進一步地,當你調試程序中較大的組成部分時,你就可以確信那些較小的組成部分是正常工作的。
徹底調試好程序的一個組成部分後,再調試下一個組成部分
這一點非常重要。如果證實了程序的一個組成部分是正確的,不僅能縮小可能存在錯誤的范圍,而且程序的其它組成部分就能安全地使用這部分程序了。這里應用了一種很好的經驗性原則,簡單地說就是調試一段代碼的難度與這段代碼長度的平方成正比,因此,調試一段20行的代碼比調試一段10行的代碼要難4倍。因此,在調試過程中每次只把精力集中在一小段代碼上是很有幫助的。當然,這僅僅是一個總的原則,具體使用時還要視具體情況而定。
連續地觀察程序流(flow)和數據的變化
這一點也很重要!如果你小心仔細地設計和編寫程序,那麼通過監視程序的輸出你就能准確地知道正在執行的是哪部分代碼以及各個變數的內容都是什麼。當然,如果程序表現不正常,你就無法做到這一點。為了做到這一點,通常只能藉助於調試程序或者在程序中加入大量的print語句來觀察控制流和重要變數的內容。
始終打開編譯程序警告選項 並試圖消除所有警告
在開發程序的過程中,你自始至終都要做到這一點,否則,你就會面臨一項十分繁重的工作。盡管許多程序員認為消除編譯程序警告是一項繁瑣的工作,但它是很有價值的。編譯程序給出警告的大部分代碼至少都是有問題的,因此用一些時間把它們變成正確的代碼是值得的;而且,通過消除這些警告,你往往會找到程序中真正發生錯誤的地方。
准確地縮小存在錯誤的范圍
如果你能一下子確定存在錯誤的那部分程序並在其中找到錯誤,那就會節省許多調試時間,並且你能成為一個收入相當高的專業調試員。但事實上,我們並不能總是一下子就命中要害,因此,通常的做法是逐步縮小可能存在錯誤的程序范圍,並通過這種過程找出真正存在錯誤的那部分程序。不管錯誤是多麼難於發現,這種做法總是有效的。當你找到這部分程序後,就可以把所有的調試工作集中到這部分程序上了。不言而喻,准確地縮小范圍是很重要的,否則,最終集中精力調試的那部分程序很可能是完全正確的。
如何從一開始就避免錯誤?
有這樣一句諺語——「防患於未然」,它的意思是避免問題的出現比出現問題後再想辦法彌補要好得多。這在計算機編程中也是千真萬確的!在編寫程序時,一個經驗豐富的程序員所花的時間和精力要比一個缺乏經驗的程序員多得,但正是這種耐心和嚴謹的編程風格使經驗豐富的程序員往往只需花很少的時間來調試程序,而且,如果此後程序要解決某個問題或做某種改動,他便能很快地修正錯誤並加入相應的代碼。相反,對於一個粗製濫造的程序,即使它總的來說還算正確,那麼改動它或者修正其中一個很快就暴露出來的錯誤,都會是一場惡夢。
一般來說,按結構化程序設計原則編寫的程序是易於調試和修改的,下面將介紹其中的一些原則。
程序中應有足夠的注釋
有些程序員認為注釋程序是一項繁瑣的工作,但即使你從來沒想過讓別人來讀你的程序,你也應該在程序中加入足夠的注釋,因為即使你現在認為清楚明了的語句,在幾個月以後往往也會變得晦澀難懂。這並不是說注釋越多越好,過多的注釋有時反而會混淆代碼的原意。但是,在每個函數中以及在執行重要功能或並非一目瞭然的代碼前加上幾行注釋是必要的。下面就是一段注釋得較好的代碼:
/*
* Compute an integer factorial value using recursion.
* Input an integer number.
* Output : another integer
* Side effects : may blow up stack if input value is * Huge *
*/
int factorial ( int number)
{
if ( number < = 1)
return 1; /* The factorial of one is one; QED * /
else
return n * factorial( n - 1 );
/ * The magic! This is possible because the factorial of a
number is the number itself times the factorial of the
number minus one. Neat! * /
}
函數應當簡潔
按照前文中曾提到的這樣一條原則——調試一段代碼的難度和這段代碼長度的平方成正比——函數編寫得簡潔無疑是有益的。但是,需要補充的是,如果一個函數很簡潔,你就應該多花一點時間去仔細地分析和檢查它,以確保它准確無誤。此後你可以繼續編寫程序的其餘部分,並且可以對剛才編寫的函數的正確性充滿信心,你再也不需要檢查它了。對於一段又長又復雜的常式,你往往是不會有這樣的信心的。
編寫短小簡潔的函數的另一個好處是,在編寫了一個短小的函數之後,在程序的其它部分就可以使用這個函數了。例如,如果你在編寫一個財務處理程序,那麼你在程序的不同部分可能都需要按季、按月、按周或者按一月中的某一天等方式來計算利息。如果按非結構化原則編寫程序,那麼在計算利息的每一處都需要一段獨立的代碼,這些重復的代碼將使程序變得冗長而難讀。然而,你可以把這些任務的實現簡化為下面這樣的一個函數:
/*
* ComDllte what the "real" rate of interest would be
* for a given flat interest rate, divided into N segments
*/
double Compute Interest( double Rate, int Segments )
{
int a;
double Result = 1.0;
Rate /= (double) Segments;
for( a = 0; a< Segments ; ++a )
Result * =Rate;
return Result;
}
在編寫了上述函數之後,你就可以在計算利息的每一處調用這個函數了。這樣一來,你不僅能有效地消除每一段復制的代碼中的錯誤,而且大大縮短了程序的長度,簡化了程序的結構。這種技術往往還會使程序中的其它錯誤更容易被發現。
當你習慣了用這種方法把程序分解為可控制的模塊後,你就會發現它還有更多的妙用。
程序流應該清晰,避免使用goto語句和其它跳轉語句
這條原則在計算機技術領域內已被廣泛接受,但在某些圈子中對此還很有爭議。然而,人們也一致認為那些通過少數語句使程序流無條件地跳過部分代碼的程序調試起來要容易得多,因為這樣的程序通常更加清晰易懂。許多程序員不知道如何用結構化的程序結構來代替那些「非結構化的跳轉」,下面的一些例子說明了應該如何完成這項工作:
for( a = 0; a<100s ++a)
{
Func1( a );
if (a = = 2 ) continue;
Func2( a );
}
當a等於2時,這段程序就通過continue語句跳過循環中的某余部分。它可以被改寫成如下的形式:
for( a = 0; a<100; ++a)
{
Func1 (a);
if (a !=2 )
Func2(a) ;
}
這段程序更易於調試,因為花括弧內的代碼清楚地顯示了應該執行和不應該執行什麼。那麼,它是怎樣使你的代碼更易於修改和調試的呢?假設現在要加入一些在每次循環的最後都要被執行的代碼,在第一個例子中,如果你注意到了continue語句,你就不得不對這段程序做復雜的修改(不妨試一下,因為這並非是顯而易見的!);如果你沒有注意到continue語句,那麼你恐怕就要犯一個難以發現的錯誤了。在第二個例子中,要做的修改很簡單,你只需把新的代碼加到循環體的末尾。
當你使用break語句時,可能會發生另外一種錯誤。假設你編寫了下面這樣一段程序:
for (a =0) a<100; ++a)
{
if (Func1 (a) ==2 )
break;
Func2 (a) ;
}
假設函數Funcl()的返回值永遠不會等於2,上述循環就會從1進行到100;反之,循環在到達100以前就會結束。如果你要在循環體中加入代碼,看到這樣的循環體,你很可能就會認為它確實能從0循環到99,而這種假設很可能會使你犯一個危險的錯誤。另一種危險可能來自對a值的使用,因為當循環結束後,a的值並不一定就是100。
c語言能幫助你解決這樣的問題,你可以按如下形式編寫這個for循環:
for(a=O;a<100&&Func1(a)!=2;++a)
上述循環清楚地告訴程序員:「從0循環到99,但一旦Func1()等於2就停止循環」。因為整個退出條件非常清楚,所以程序員此後就很難犯前面提到的那些錯誤了。
函數名和變數名應具有描述性
使用具有描述性的函數和變數名能更清楚地表達代碼的意思——並且在某種程度上這本身就是一種注釋。以下幾個例子就是最好的說明:
y=p+i-c;
和
YearlySum=Principal+Interest-Charges:
哪一個更清楚呢?
p=*(l+o);
和
page=&List[offset];
哪一個更清楚呢?
『肆』 c語言中的調試有什麼作用
相當有用。在你編的程序,編譯後出錯了,你又找不出。就用debug。去糾錯。這個debug的功能其實就是把每一步產生的變數值替你列出來。讓你一步步檢查。當然你要檢查的變數要你先選定好。這是它的原理,還有一點點細節,你自己去試吧。
不過這個也不會一直用,因為邏輯或者是語法上的錯誤大多數情況下,可以直接看出來。沒必要用debug
『伍』 設計和調試c語言需要哪四個階段
最先是分析需求,設計程序,編輯程序,調試程序,這四個階段。
『陸』 c語言中什麼叫做單步調試,步驟是什麼
單步調試是指程序開發中,為了找到程序的bug,通常採用的一種調試手段,一步一步跟蹤程序執行的流程,根據變數的值,找到錯誤的原因。
解山並局決這個問題的方法如下:
1、首先需要設置斷點的那一行代碼的最前面點逗讓擊蔽仿下,就會出現一個紅色的圓球,代表設置斷點成功,下圖一共設置了4個斷點。
『柒』 C語言中編譯 生成 調試 測試 運行各是什麼意思有什麼區別
C語言中編譯 生成 調試 測試 運行的區別如下:
區別一:
從編譯方面來看:
編譯依賴於編譯器,英文是compile, vc中這一過程是將源代碼轉換成目標文件,如:obj文件,rc文件等。
區別二:
從生成方面來看:
生成指的是連接的過程,英文是build,依賴於鏈接器。vc中在這一階段將所有的目標文件和所有需要用到的組件組合成一個整體,例如需要生成的是windows系統下的PE可執行文件,鏈接器會依照特定格式將目標文件組合,最後生成PE格式的,exe或dll文件。
區別三:
從調試方面來看:
調試是所有或部分代碼編寫完成後,讓程序在調試器中運行,用這種手段對程序進行分析,找出並修正潛在問題。
區別四:
從運行方面來看:
運行就是讓程序在系統中運行。
(7)c語言調試為什麼只有構建擴展閱讀:
C語言的介紹:
C語言是目前流行的通用程序設計語言,是計算機專業人員和計算機愛好者開發軟體的首選開發工具。C語言源程序必須經過某種編譯工具翻譯成為目標機器語言程序才能夠在計算機上執行。
然而隨著程序編寫規模的擴大,順利編寫出正確的程序絕非一件容易的事情,早期的許多編譯工具僅僅提供翻譯功能,已滿足不了應用的要求,編程人員需要-種功能全面並高度集成的編譯環境。
程序是一段具有一定功能的代碼,編寫程序的目的是解決問題。當程序人員寫完程序後,其實並不起作用,只有當編寫的程序經過一系列的處理後,能夠解決問題時。
序才成為真正的程序,這一系列的處理過程,-般就是編輯、編譯、連接、調試與運行等。目前最成熟的C語言集成環境主要有Turbo C2.0和Turbo C 3.0( 簡稱TC30)或Borland C++3.1( 簡稱BC31)以及Visual C++ 6.0。