标签:
1.多文件编译、链接的原理
在讲解 extern 和 static 关键字的时候,我们已经给出了几个简单的多文件编程的例子,现在不妨再看一个例子。
main.c 源码:
- #include <stdio.h>
- #include <conio.h>
- // 也可以不写 extern;为了程序可读性,建议写上
- extern long sum(int, int);
- // 必须写 extern
- extern char* OS;
- int main()
- {
- int n1 = 1, n2 = 100;
- printf("从%d加到%d的和为%ld [By %s]", n1, n2, sum(n1, n2), OS);
- getch();
- return 0;
- }
- #include <stdio.h>
- // 当前操作系统
- char *OS = "Windows 7";
- long sum(int fromNum, int endNum){
- int i;
- long result = 0;
- // 参数不符合规则,返回 -1
- if(fromNum<0 || endNum<0 || endNum<fromNum){
- return -1;
- }
- for(i=fromNum; i<=endNum; i++){
- result += i;
- }
- // 返回大于等于0的值
- return result;
- }
2.C语言模块化编程中的头文件
上节我们编写了
main.c 和 module.c 两个源文件,并在 module.c 中定义了一个函数和一个全局变量,然后在 main.c 中进行了声明。
不过实际开发中很少这样做,一般是将函数和变量的声明放到头文件,再在当前的源文件中 #include 进来。而且,全局变量最好声明为 static,只在当前文件中可见,不要对外暴露;如果必须对外暴露,可以使用宏定义代替,请看下面的代码。
main.c 源码:
- #include <stdio.h>
- #include <conio.h>
- #include "module.h"
- int main()
- {
- int n1 = 1, n2 = 100;
- printf("从%d加到%d的和为%ld [By %s]", n1, n2, sum(n1, n2), OS);
- getch();
- return 0;
- }
- #include <stdio.h>
- long sum(int fromNum, int endNum){
- int i;
- long result = 0;
- // 参数不符合规则,返回 -1
- if(fromNum<0 || endNum<0 || endNum<fromNum){
- return -1;
- }
- for(i=fromNum; i<=endNum; i++){
- result += i;
- }
- // 返回大于等于0的值
- return result;
- }
- // 用宏定义来代替全局变量
- #define OS "Windows 7"
- // 也可以省略 extern;不过为了程序可读性,建议写上
- extern long sum(int, int);
3.C语言标准库以及标准头文件
源文件通过编译可以生成
.obj 文件(二进制库文件),并提供一个头文件向外暴露接口,除了保护版权,还可以将散乱的文件打包,便于发布和使用。
实际上我们一般不直接向用户提供 .obj 文件,而是将多个 .obj 文件打包成 .lib 文件(静态库)或 .dll 文件(动态库)。
.obj 打包成 .lib 或 .dll 也要经过链接的过程来找到函数入口、变量声明等,在VC中可以直接创建相应的工程来生成(与创建 Win32 Console Application
类似,后续会讲解)。
.lib 和 .dll 可以看成是一堆 .obj 的集合,虽然有入口函数,但不能直接运行,必须被链接到 .exe 或被 .exe 调用。
C语言在发布时已经将常用的函数、宏、类型定义等打包到了静态库,并提供了相应的头文件。如果你使用的是VC,那么在安装目录下的 \VC98\Include\ 文件夹中会看到很多头文件,包括我们常用的
stdio.h、stdlib.h 等;在 \VC98\Lib\ 文件夹中有很多 .lib 文件,这就是我们链接时要用到的静态库。
例如我的 VC6.0 安装在 C:\Program Files\Microsoft Visual Studio\ 目录,那么 VC6.0 附带的所有头文件都在 C:\Program
Files\Microsoft Visual Studio\VC98\Include\ 目录下,所有 .lib 文件都在 C:\Program Files\Microsoft Visual Studio\VC98\Include\Lib\ 目录下。
如果忘记 VC6.0 的安装目录或者头文件不在安装目录下,可以通过以下方式找到:
1) 在工具栏中点击“工具”按钮
2) 在二级菜单中选择“选项”
3) 在弹出的对话框中选择“目录”标签
4) 然后选择名字为“目录”的下拉菜单中的“Include files”一项,如下图所示:
ANSI C 规范共定义了 15 个头文件,称为“C标准库”,所有的编译器都必须支持,如何正确并熟练的使用这些标准库,可以反映出一个程序员的水平:
- #include <stdio.h>
- #include "myFile.h"
4.C语言头文件的特性和规范
头文件通过
#include 命令包含到当前文件,效果与直接复制头文件的内容相同;编译器在预处理阶段实际上也是这样做的。
不管是标准头文件还是我们自己编写的头文件,都应该遵循等幂性:可以多次包含相同的头文件,但效果与只包含一次相同。
等幂性很容易实现,对于大多数的头文件可以使用宏保护。例如,在 stdio.h 中可以有如下的宏定义:
- #ifndef _STDIO_H
- #define _STDIO_H
- /* 声明部分 */
- #endif
5.C语言头文件的路径
引入编译器自带的头文件(包括标准头文件)用尖括号,引入自定义头文件用双引号,例如:
- #include <stdio.h>
- #include "myFile.h"
- #include "include/func.h"
- #include "../include/func.h" /* ../ 表示上级目录 */
- #include "E:\demo\include\func.h"
6.一个比较规范的C语言多文件编程的例子
这一节向大家展示一个比较规范的多文件编程的例子,将前面几节的知识运用起来。
通过 VC 6.0 创建一个工程,保存到 E:\demo 目录,工程文件有:
main.c 源码:
- #include <stdio.h>
- #include <conio.h>
- #include "include/func.h"
- int main()
- {
- int n1 = 1, n2 = 10;
- printf("从%d加到%d的和为%ld\n", n1, n2, sum(n1, n2));
- printf("从%d乘到%d的积为%ld\n", n1, n2, mult(n1, n2));
- printf("OS:%s\n",OS);
- printf("Power By %s(%s)", getWebName(), getWebURL());
- getch();
- return 0;
- }
- // 没有使用到 func.h 中的函数声明或宏定义,也可以不包含进来
- #include "../include/func.h"
- // 从 fromNum 加到 endNum
- long sum(int fromNum, int endNum){
- int i;
- long result = 0;
- // 参数不符合规则,返回 -1
- if(fromNum<0 || endNum<0 || endNum<fromNum){
- return -1;
- }
- for(i=fromNum; i<=endNum; i++){
- result += i;
- }
- // 返回大于等于0的值
- return result;
- }
- // 从 fromNum 乘到 endNum
- long mult(int fromNum, int endNum){
- int i;
- long result = 1;
- // 参数不符合规则,返回 -1
- if(fromNum<0 || endNum<0 || endNum<fromNum){
- return -1;
- }
- for(i=fromNum; i<=endNum; i++){
- result *= i;
- }
- // 返回大于等于0的值
- return result;
- }
- // 使用到了 func.h 中的宏定义,必须包含进来,否则编译错误
- #include "../include/func.h"
- char* getWebName(){
- return WEB_NAME;
- }
- char* getWebURL(){
- return WEB_URL;
- }
- #ifndef _FUNC_H
- #define _FUNC_H
- // 用宏定义来代替全局变量
- #define OS "Windows 7"
- #define WEB_URL "http://c.biancheng.net"
- #define WEB_NAME "C语言中文网"
- // 也可以省略 extern,不过为了程序可读性,建议都写上
- extern long sum(int, int);
- extern long mult(int, int);
- extern char* getWebName();
- extern char* getWebURL();
- #endif
标签:
原文地址:http://blog.csdn.net/shuimanting520/article/details/51360156