UNIX
假定在UNIX系统中安装了UNIX C编译器cc(最初的cc已经停用,但是许多UNIX系统都给cc命令起了一个别名用作其他编译器命令,典型的是gcc或clang)。假设file1.c和file2.c是两个内含C函数的文件,下面的命令将编译两个文件并生成一个名为a.out的可执行文件:
cc file1.c file2.c
另外,还生成两个名为file1.o和file2.o的目标文件。如果后来改动了file1.c,而file2.c不变,可以使用以下命令编译第1个文件,并与第2个文件的目标代码合并:
cc file1.c file2.o
UNIX系统的make命令可自动管理多文件程序。
注意,OS X的Terminal工具可以打开UNIX命令行环境,但是必须先下载命令行编译器(GCC和Clang).
Linux
假定Linux系统安装了GNU C编译器GCC。假设file1.c和file2.c是两个内含C函数的文件,下面的命令将编译两个文件并生成名为a.out的可执行文件:
gcc file1.c file2.c
另外,还生成两个名为file1.o和file2.o的目标文件。如果后来改动了file1.c,而file2.c不变,可以使用以下命令编译第1个文件,并与第2个文件的目标代码合并:
gcc file1.c file2.o
DOS命令行编译器
绝大多数DOS命令行编译器的工作原理和UNIX的cc命令类似,只不过使用不同的名称而已。其中一个区别是,对象文件的扩展名是.obj,而不是.o。一些编译器生成的不是目标代码文件,而是汇编语言或其他特殊代码的中间文件。
Windows和苹果的IDE编译器
Windows和Macintosh系统使用的集成开发环境中的编译器是面向项目的。项目描述的是特定程序使用的资源。资源包括源代码文件。这种IDE中的编译器要创建项目来运行单文件程序。对于多文件程序,要使用相应的菜单命令,把源代码文件加入一个项目。要确保所有的源代码文件都在项目列表中列出。许多IDE都不用在项目列表中列出头文件(即扩展名为.h的文件),因为项目只管理使用的源代码文件,源代码文件中的#include指令管理该文件中使用的头文件。但是,Xcode要在项目中添加头文件。
使用头文件
如果把main()放在第1个文件中,把函数定义放在第2个文件中,那么第1个文件仍然要使用函数原型。把函数原型放在头文件中,就不用在每次使用函数时都写出函数的原型。C标准库就是这样做的,例如,把I/O函数原型放在stdio.h中,把数学函数原型放在math.h中,你也可以这样用自定义的函数文件。
另外,程序中经常用C预处理器定义符号常量。这种定义只储存了那些包含#define指令的文件。如果把程序的一个函数放进一个独立的文件中,你也可以使用#define指令访问每个文件。最直接的方法是在每个文件中再次输入指令,但是这个方法既耗时又容易出错。另外,还会有维护的问题:如果修改了#define定义的值,就必须在每个文件中修改。更好的做法是,把#define指令放进头文件,然后在每个源文件中使用#include指令包含该文件即可。
总之,把函数原型和已定义的字符常量放在头文件中是一个良好的编译习惯。
示例:让用户指定酒店和入住天数,然后计算并显示总费用
usehotel.c
//Visual Studio中加上这句才可以使用scanf() //否则只能使用scanf_s() #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdbool.h> #include "hotel.h" //argc: 参数个数 argv[]: 参数数组 int main(int argc, char *argv[]) { int nights; double hotel_rate; int code; while ((code = menu()) != QUIT) { switch (code) { case 1: hotel_rate = HOTEL1; break; case 2: hotel_rate = HOTEL2; break; case 3: hotel_rate = HOTEL3; break; case 4: hotel_rate = HOTEL4; break; default: hotel_rate = 0.0; printf("Oops!\n"); break; } nights = getnights(); showprice(hotel_rate, nights); } printf("Thank you and goodbye.\n"); system("pause"); return 0; }
hotel.h
#pragma once #define QUIT 5 #define HOTEL1 180.00 #define HOTEL2 225.00 #define HOTEL3 255.00 #define HOTEL4 355.00 #define DISCOUNT 0.95 #define STARTS "********************************" // 显示选择列表 int menu(void); // 返回预订天数 int getnights(void); // 根据费率、入住天数计算费用 // 并显示结果 void showprice(double rate, int nights);
hotel.c
/* hotel.cs -- 酒店管理函数 */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include "hotel.h" int menu(void) { int code, status; printf("\n%s%s\n", STARTS, STARTS); printf("Enter the number of the desired totel:\n"); printf("1) Fairfield Arms 2) Hotel Olympic\n"); printf("3) Chertworthy Plaza 4) The Stockton\n"); printf("5) quit\n"); printf("%s%s\n", STARTS, STARTS); while ((status = scanf("%d", &code)) != 1 || (code < 1 || code > 5)) { if (status != 1) scanf("%*s"); //处理非整数输入 printf("Enter an integer from 1 to 5, please.\n"); } return code; } int getnights(void) { int nights; printf("How many nights are needed? "); while (scanf("%d", &nights) != 1) { scanf("%*s"); //处理非整数输入 printf("Please enter an integer, such as 2.\n"); } return nights; } void showprice(double rate, int nights) { int n; double total = 0.0; double factor = 1.0; for (n = 1; n <= nights; n++, factor *= DISCOUNT) total += rate * factor; printf("The total cost will be $%0.2f.\n", total); }
运行测试