最普遍的错误是编译正确,运行出错。这往往出现在多个文件的配合上。需要注意的是,在多文件编程中,它的每一个文件C源程序文件都可以单独编译查错,但头文件不能编译。
在多文件查错时,一定要注意相关联的变量是否正确。
【例23.1】文件23_1.c和23_11.c的内容如下:
//23_1.cchar 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.hchar 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:50Value is 50OKInput a value:55Value is 55Value problem
现在的集成环境使用工程管理,应该按多文件编程规范编程。
可以按编制C程序使用程序文件(包括头文件和源程序文件)的数量来分类,将其分为单文件结构和多文件结构,而且单文件结构没有自己定义的头文件。多文件结构又可以按编制C程序源文件的多少分为两类,一类是只有一个源程序文件,另一类有多个源程序文件。下面就介绍C语言的典型程序结构以方便编程。