不知道是不是有人和我一样,在使用C语言中存在这两个误解。当然这里指的是非专为人事,在靠C吃饭的人看来,这些根本就不是问题。不过专业人事也是从新手过来的,以前有过么?若有那可能不完全是我的问题了,若没有,那还真是自己的问题啊。
第一个误解,源于对编译、链接没能分清楚,因为通常在IDE里点一个地方就能得到可执行程序了。这直接导致对文件的包含关系,头文件的作用理解不到位,总是搞不清楚一大堆C文件如何组织成一个程序的。比如,我原以为全局变量与各个函数的声明要写在头文件里,而函数的定义则写在相应的.c文件里。这事实上存在一定的陷患,在有多个地方均包含同一头文件时容易出现链接错误。现在我自己觉得,对于C程序而言,应该以源文件为单位,分别编写并独立编译,这样保障各部分的正确性。而头文件中内容其实主要是供给其它源文件使用的,即这个模块中的那些希望函数被别的模块所调用,那么则将其声明写在头文件中,当然这个头文件也供本模块在编译时使用。所以,头文件并不是C程序构成的要件。
下面这个简单的例子,可以帮助理解上述关系。程序执行后在屏幕上输出整数3。源程序由两个.c源文件构成。
/*file1.c*/
#include<stdio.h>
int get3();
int main()
{
int a;
a=get3();
printf("%d/n",a);
}
/*file2.c*/
int get3()
{
int a=3;
return a;
}
通过命令 gcc -c file1.c 和 gcc -c file2.c 可分别得到目标文件file1.o和file2.o。在file1.c中主函数调用了函数get3(),所以要先声明它,当然也可包含一个含用get3()声明的头文件。如果少了声明,而编译无法通过。在file2.c中因为get3函数没有调用任何函数,所以也无须什么声明,直接就要编译成功。编译完成后,再用命令gcc file1.o file2.o -o test可得到名为test的可执行文件。
总之,就说明了一个问题,用到之前要先声明,要给其它文件的函数调用才写入头文件。下面把file2进行改写并编译,重新链接可得到新的可执行程序,此时执行结果为7,而file1没有必要重要编译。
int add5(int x);
int get3()
{
int a=2;
return add5(2);
}
int add5(int x)
{
return x+5;
}
第二个误解就比较简单了,是关于格式化输入输出的。一般C语言书上在格式化输出printf的部分会用表格列出格式化字符,而在讲fscanf时则一笔带过,只说它与scanf相对应。那么我就想当然地理解为适用于printf的格式化字符也适用于fscanf。这让我狠伤了一阵脑筋,因为我要输入一堆用科学计数法表示的数据。现在知道了,输入时用"%lf”,输出时用"%e"或%E",而且输出时还可指定精度。
的确只是简单问题,写下来只是为了让自己更清晰。