最普遍的錯誤是編譯正確,運行出錯。這往往出現在多個文件的配合上。需要注意的是,在多文件編程中,它的每一個文件C源程序文件都可以單獨編譯查錯,但頭文件不能編譯。
在多文件查錯時,一定要注意相關聯的變量是否正確。
【例23.1】文件23_1.c和23_11.c的內容如下:
//23_1.c char str = "How are you ?" ; //23_11.c #include <stdio.h> extern char *str ; int main () { printf ("%s\n" ,str ); return 0 ; }
程序編譯通過,但運行出錯。找出原因並改正。
【解答】雖然說字符數組和字符指針幾乎可以在C++任何地方進行互換使用,但這裡確是它們不能互換使用的少有的幾種情況之一。在這種情況下,主程序main認為str是一個指針,因此它運行到那個位置,讀該地址的前4位,如圖23-1所示,前4位正好是「How」,它不是一個地址,所以出現運行時錯誤。
圖23-1 地址示意圖
將23_1.c的聲明改為
extern char str ;
即可。但這種是沿襲過去的編程方法,在集成環境中,聲明遵循在頭文件中定義或聲明外部變量,該頭文件應該被所有定義或使用該項的文件包含。
將23_11.c改為23_1.h,按集成環境管理的方法,23_1.c中的聲明語句不再需要了。程序結構如下:
//23_1.h char str = "How are you ?" ; //23_1.c #include <stdio.h> #include "23_1.h" int main () { printf ("%s\n" ,str ); return 0 ; }
【例23.2】文件23_2.c和23_21.c的內容如下:
//23_21.c #include <stdio.h> int value = 60 ; void checkeven (void ) { if (( value % 2 ) == 0 ) printf ("OK\n" ); else printf ("Value problem\n" ); } //23_2.c #include <stdio.h> int value = 51 ; extern void checkeven (void ); int main () { checkeven (); printf ("Value is %d\n" ,value ); return 0 ; }
該程序通過第1次編譯,但不能通過第2次,即不能生成執行文件。找出原因並改正。
【解答】錯誤地在兩個文件裡定義同名變量,結果具有編譯依賴性。可以使用static將它們定義為各自的局部變量。如果使用不同的文件名,因為文件23_21.c見不到文件23_2.c的變量,所以必須在這個文件對23_2.c中定義的變量聲明為外部變量。但這都不是理想的辦法,因為23_21.c根本沒使用自己文件定義的變量。應該將變量和函數聲明在頭文件中,供每個文件使用它。這裡在23_21.c中增加使用變量的打印語句以驗證調用。修改後的3個文件如下:
//23_2.h #include <stdio.h> void checkeven (void ); int value ; //23_21.c #include "23_2.h" void checkeven (void ) { printf ("Value is %d\n" ,value ); if (( value % 2 ) == 0 ) printf ("OK\n" ); else printf ("Value problem\n" ); } //23_2.c #include "23_2.h" int main () { printf ("Input a value :" ); scanf ("%d" , &value ); checkeven (); return 0 ; }
程序兩次示範運行的結果如下:
Input a value : 50 Value is 50 OK Input a value : 55 Value is 55 Value problem
現在的集成環境使用工程管理,應該按多文件編程規範編程。
可以按編制C程序使用程序文件(包括頭文件和源程序文件)的數量來分類,將其分為單文件結構和多文件結構,而且單文件結構沒有自己定義的頭文件。多文件結構又可以按編制C程序源文件的多少分為兩類,一類是只有一個源程序文件,另一類有多個源程序文件。下面就介紹C語言的典型程序結構以方便編程。