第9章 预处理命令
- 格式:docx
- 大小:17.05 KB
- 文档页数:3
1.下面叙述中正确的是(A )。
A.带参数的宏定义中参数是没有类型的B.宏展开将占用程序的运行时间C.宏定义命令是C语言中的一种特殊语句D.使用#include命令包含的头文件必须以“.h”为后缀2.在宏定义#define PI3.14159中,用宏名代替一个( D )A.常量B.单精度数C.双精度数D.字符串3.下面有关宏替换的叙述不正确的是( D )A.宏替换不占用运行时间B.宏名无类型C.宏替换只是字符替换D.宏名必须用大写字母表示4.C语言的编译系统对宏命令的处理是( D )A.在程序运行时进行的B.和C程序中的其他语句同时进行编译的C.在程序连接时进行的D.在对源程序中其它成分正式编译之前进行的5.下列定义不正确的是(C )。
A.#define PI 3.141592B.#define S345C.int max(x,y); int x,y; { }D.static char c6.有如下宏定义 #define s(a) a*3 ,则执行表达式x=s(1+2)后,变量x的值为( D)。
A.10B.9C.8D.77.以下说法中正确的是( D)。
A.#define是C语句B.#define是库函数C.#define是自定义函数D.#define是预处理命令8.在“文件包含”预处理语句的使用形式中,当#include后面的文件用了“”(双引号)时,寻找被包含文件的方式是(B)。
A.直接按系统设定的标准方式搜索目录B.先在源程序所在目录搜索,再按系统设定的标准方式搜索C.仅仅搜索源程序所在目录D.仅仅搜索当前目录9.以下叙述正确的是( B )。
A.可以把define和if定义为用户标识符B.可以把define定义为用户标识符,但不能把if定义为用户标识符C.可以把if定义为用户标识符,但不能把define定义为用户标识符D.define和if都不能定义为用户标识符10.以下叙述中正确的是( B )。
#pragma#pragma 预处理指令详解在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。
#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。
依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
其格式一般为: #Pragma Para其中Para 为参数,下面来看一些常用的参数。
(1)message 参数。
Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。
其使用方法为:#Pragma message(“消息文本”)当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。
假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法#ifdef _X86#Pragma message(“_X86 macro activated!”)#endif当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated!”。
我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。
(2)另一个使用得比较多的pragma参数是code_seg。
格式如:#pragma code_seg( ["section-name"[,"section-class"] ] )它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
(3)#pragma once (比较常用)只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。
.net 预处理详解在使用.net框架进行软件开发时,我们经常会遇到需要在编译阶段对代码进行预处理的情况。
预处理是指在编译代码之前,通过指定一些预处理指令来控制代码的编译过程。
预处理指令在代码中以`#`符号开头,告诉编译器应该如何处理代码。
在本文中,我们将详细介绍.net 框架中常用的预处理指令及其用法。
1. 条件编译条件编译是预处理中最常用的功能之一,它可以根据一些条件来决定是否编译一段特定的代码。
通过使用`#if`和`#endif`指令,我们可以在代码中嵌入任意条件来控制编译过程。
例如,我们可以使用条件编译来根据不同的操作系统平台编译不同的代码片段:```csharp#if WINDOWSConsole.WriteLine("This is a Windows platform.");#elif LINUXConsole.WriteLine("This is a Linux platform.");#endif```上述代码中,`#if`指令用于判断是否为Windows平台,如果是则输出相应的信息;`#elif`指令用于判断是否为Linux平台,如果是则输出相应的信息。
通过条件编译,我们可以根据具体情况选择性地编译代码,以实现更好的跨平台兼容性。
2. 定义常量预处理指令还可以用于定义常量,在编译过程中将其替换为指定的值。
通过`#define`指令可以定义一个常量,并在代码中使用该常量。
例如:```csharp#define MAX_VALUE 100int value = MAX_VALUE;```上述代码中,我们使用`#define`指令定义了一个名为`MAX_VALUE`的常量,并将其设置为100。
之后,在代码中使用该常量时,编译器会将其替换为实际的值。
这样可以提高代码的可读性和维护性。
3. 跳过代码有时候,在调试或者测试代码时,我们需要暂时跳过一些代码片段而不编译它们。
第九章编译预处理课题:第九章编译预处理教学目的:1、了解预处理的概念及特点2、掌握有参宏与无参宏的定义及使用,领会文件包含的使用及效果教学重点:教学难点:掌握宏的使用,文件包含有参宏与无参宏的使用步骤一复习引导ANSI C标准规定可以在C源程序中加入一些“预处理命令”,以改进程序设计环境,提高编程效率。
这些预处理命令是由ANSI C统一规定的,但它不是C语言本身的组成部分,不能直接对它们进行编译。
必须在对程序进行通常的编译之前,先对程序中这些特殊的命令进行“预处理”,即根据预处理命令对程序作相应的处理。
经过预处理后程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。
步骤二讲授新课C语言与其他高级语言的一个重要区别是可以使用预处理命令和具有预处理的功能。
C 提供的预处理功能主要有以下三种:宏定义、文件包含、条件编译。
分别用宏定义命令、文件包含命令、条件编译命令来实现。
为了与一般C语句相区别,这些命令以符号“ #” 开头。
§9.1宏定义宏:代表一个字符串的标识符。
宏名:被定义为“宏”的标识符。
宏代换(展开):在编译预处理时,对程序中所有出现的“宏名”,用宏定义中的字符串去代换的过程。
一、不带参数的宏定义一般形式:#define 标识符字符串#define PI 3.1415926main(){ float l, s, r, v;printf( “input radius:” );scanf( “%f”, &r );l = 2.0*PI*r;s = PI*r*r;v = 3.0/4*PI*r*r*r;printf(“%10.4f,%10.4f,%10.4\n”, l, s, v);}例如:由键盘输入y值,求表达式:3(y2+3y)+ 4(y2+3y)+ y(y2+3y)#define M (y*y+3*y)main(){ int s, y;printf( “Input a number :”); scanf (“%d”,&y);s=3*M+4*M+y*M; p rintf(“s=%d\n”,s);}先宏展开:s=3*(y*y+3*y) +4*( y*y+3*y) + y*(y*y+3*y)再与源程序合并说明:⑴宏名一般用大写表示,以便与变量名区分。
C语言教案第九章预处理命令1.C语言中以“#”号开头的行,均为“编译预处理”命令行2.宏作为一个预处理命令,只是简单的文本代换3.在字符串代换过程中,一定要注意不要添加任何字符4.不带参数的宏定义及使用,注意宏中括号的用法5.*当宏定义在一行中写不下,需换行时应在最后一个字符后加“\”6.带参数的宏定义及使用7.注意宏名一般使用大写字母,而参数则不限8.文件包含的两种方法(书上212页)9.*条件编译习题217页:2,3,5第十章指针1.地址和指针的概念,指针型变量的定义2.指针型变量的基类型3.取地址运算符& 和指针运算符*4.通过指针为变量赋值及通过指针找出变量的值的方法5.*为指针变量赋“空”值:p=NULL或p=’\0’ 或p=0(NULL为预定义符,ASCII码值为0)6.函数的形参为指针变量时的数据传递7.通过传送地址值,在被调函数中直接改变主调函数中变量的值8.*函数返回地址值9.指针变量取代数组作函数参数10.一维数组与指针11.一维数组中的几种等价形式:设有定义int a[10], *p=a;数组元素的地址——&a[i], a+i, p+i, &p[i]数组元素——a[i], *(a+i), *(p+i), p[i]12.移动指针,每次移动一个单元13.*指针比较,通常两个或多个指针指向同一目标时比较才有意义14.*数组元素的地址作实参15.*函数的指针形参与函数体中数组的区别16.二维数组与指针17.一个二维数组可看作由多个一维数组构成18.几种等价形式:设有定义int a[5][6], *p=a[0]; 则存在着关于变量和变量的地址间的如下等价形式二维数组元素的地址——&a[i][j], a[i]+j, *(a+i)+j, &a[0][0]+列数*i+j,a[0]+列数*i+j 二维数组元素——a[i][j], *(a[i]+j), *(*(a+i)+j), *(&a[0][0]+列数*i+j),(*(a+i))[j]19.指向指针的指针:int a[5][6], **p=a;20.指针数组:int a[5][6], *p[4]; 定义了具有四个元素的基本整型指针数组21.行指针:int a[5][6], (*p)[6]; 定义了一个指向具有六个元素的一维数组的指向指针的指针型变量22.*二维数组名和指针数组作为实参在函数中的数据传递23.*二级指针和行指针作为实参在函数中的数据传递24.*字符串与指针,直接用字符型指针变量记录字符串的地址25.*指向函数的指针习题278页:2,3,4,9,10,14,15。
第九章习题答案一、单项选择题1.A2.B3.C4.D5.B6.C7.A8.D9.D10.C11.B12.C13.D14.C二、填充题1.编译处理编译预处理2.非静态存储类型变量和外部函数3.74.printf(“%d\n”,m);5.fopen(“a.txt”,”rw”);6.x[i]>=’A’&&x[i]<=’Z’7.“ i=%d\n”8.(1) #define MAX(a,b,c)(2) #define MIN(a,b) (a<b?a:b)(3) #define isalnum(c) (c>=’0’&& c<=’9’)(4) #define isupper( c) (c>=’A’&& c<=’Z’)(5) #define islower( c) (c>=’a’ && c<=’z’)三、程序分析题1.运行结果: -32.运行结果: 7,473.运行结果:50 254.运行结果:x=9, y=55.运行结果:9 9 116.输出结果: x|y&z=3x^y&~z=1x&y&z=0!x|x=1~x|x=-1四、程序设计题1.解:#include <stdio.h>#include <math.h>#define S(a, b, c) 0.5* (a+b+c)#define AREA(a, b, c) sqrt (S(a, b, c)*(S(a, b, c)-a)* (S(a, b, c )-b)* (S(a, b, c)-c)) void main ( ){ float a, b, c;printf (“输入三角形的三条边长:a, b, c\n”);scanf (“%f, %f, %f”, &a, &b, &c) ;if (( a+b>c)&& (b+c>a) && (c+a>b)){ printf (“周长=%f\n”, 2*S(a, b, c ));printf (“面积=%f\n”, AREA(a, b, c ));}else printf (“a, b, c 的长度不能构成三角形\n”) ;}2.解:#include <stdio.h>#include <stdlib.h>void main (int argc, char *argv[ ]){ int a, b;if (argc<3) { printf (“Parameter missing!\n”) ; exit(0); }a=atoi (argv[1]) ;b=atoi (argv[2]) ; //在stdlib.h中有库函数atoi, 把字符串转换成整数printf (“%5d + %5d = %5d\n”, a, b, a+b) ;printf (“%5d - %5d = %5d\n”, a, b, a-b) ;printf (“%5d * %5d = %5d\n”, a, b, a*b) ;printf (“%5d / %5d = %5d\n”, a, b, a/b) ;printf (“%5d %% %5d = %5d\n”, a, b, a%b) ;}3.解:#include <stdio.h>#include <stdlib.h>void main (int argc, char *argv[]){ int i, sum=0;for (i=1; i<argc; i++) sum=sum+atoi (argv[i]) ;printf (“和= %d\n”, sum);}4.解:#include <stdio.h>#include <stdlib.h>#include <string.h>void main (int argc, char *argv[]){ if (argc<3){ printf (“Parameter missing!\n”) ; exit(0); } if ( strcmp (argv[1], argv[2])>0) puts (argv[1]) ;else puts (argv[2]) ;}。
1、预处理1、预处理命令的定义 使⽤库函数之前,应该⽤#include引⼊对应的头⽂件。
这种以#号开头的命令称为预处理命令。
所谓预处理是指在进⾏编译时的第⼀遍扫描(词法扫描和语法分析)之前所做的⼯作。
预处理是C语⾔的⼀个重要功能,它由于处理程序负责完成。
当编译⼀个程序时,系统将⾃动调⽤预处理程序对程序中“#”开头的预处理部分进⾏处理,处理完毕之后可以进⼊源程序的编译阶段。
C语⾔源⽂件要经过编译、链接才能⽣成可执⾏程序: (1)编译(Compile)会将源⽂件(.c⽂件)转换为⽬标⽂件。
对于 VC/VS,⽬标⽂件后缀为.obj;对于GCC,⽬标⽂件后缀为.o。
编译是针对单个源⽂件的,⼀次编译操作只能编译⼀个源⽂件,如果程序中有多个源⽂件,就需要多次编译操作。
(2)链接(Link)是针对多个⽂件的,它会将编译⽣成的多个⽬标⽂件以及系统中的库、组件等合并成⼀个可执⾏程序。
在实际开发中,有时候在编译之前还需要对源⽂件进⾏简单的处理。
例如,我们希望⾃⼰的程序在 Windows 和 Linux 下都能够运⾏,那么就要在 Windows 下使⽤ VS 编译⼀遍,然后在 Linux 下使⽤ GCC 编译⼀遍。
但是现在有个问题,程序中要实现的某个功能在 VS 和GCC 下使⽤的函数不同(假设 VS 下使⽤ a(),GCC 下使⽤ b()),VS 下的函数在 GCC 下不能编译通过,GCC 下的函数在 VS 下也不能编译通过,怎么办呢? 这就需要在编译之前先对源⽂件进⾏处理:如果检测到是 VS,就保留 a() 删除 b();如果检测到是 GCC,就保留 b() 删除 a()。
这些在编译之前对源⽂件进⾏简单加⼯的过程,就称为预处理(即预先处理、提前处理)。
预处理主要是处理以#开头的命令,例如#include <stdio.h>等。
预处理命令要放在所有函数之外,⽽且⼀般都放在源⽂件的前⾯。
预处理是C语⾔的⼀个重要功能,由预处理程序完成。
第9章编译预处理和动态存储分配1.以下叙述中正确的是()。
A) 在C语言中,预处理命令行都以"#"开头B) 预处理命令行必须位于C源程序的起始位置C) #include <stdio.h>必须放在C程序的开头D) C语言的预处理不能实现宏定义和条件编译的功能参考答案:A【解析】预处理命令是以"#"号开头的命令,它们不是C语言的可执行命令,这些命令应该在函数之外书写,一般在源文件的最前面书写,但不是必须在起始位置书写,所以B),C)错误。
C)语言的预处理能够实现宏定义和条件编译等功能,所以D)错误。
2.以下关于宏的叙述中正确的是()。
A) 宏替换没有数据类型限制B) 宏定义必须位于源程序中所有语句之前C) 宏名必须用大写字母表示D) 宏调用比函数调用耗费时间参考答案:A【解析】宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头,所以B)选项中宏定义必须位于源程序中所有语句之前是错误的。
宏名一般用大写,但不是必须用大写,所以C)选项错误。
宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值),所以D)选项错误。
3.有以下程序:#include <stdio.h>#define PT 3.5 ;#define S(x) PT*x*x ;main(){int a=1,b=2;printf("%4.1f\n" ,S(a+b));}程序运行后的输出结果是()。
A) 7.5 B) 31.5 C) 程序有错无输出结果D) 14.0参考答案:C【解析】宏定义不是C语句,末尾不需要有分号。
所以语句printf("%4.1f\n" ,S(a+b));展开后为printf("%4.1f\n" ,3.5;*a+b*a+b;);所以程序会出现语法错误。
第九章 预处理命令一、选择题1.以下叙述不正确的是 。
A)预处理命令行都必须以#开始B)在程序中凡是以#开始的语句行都是预处理命令行C)C程序在执行过程中对预处理命令行进行处理D)预处理命令行可以出现在C程序中任意一行上2.以下叙述中正确的是 。
A)在程序的一行上可以出现多个有效的预处理命令行B)使用带参数的宏时,参数的类型应与宏定义时的一致C)宏替换不占用运行时间,只占用编译时间D)C语言的编译预处理就是对源程序进行初步的语法检查3.以下有关宏替换的叙述不正确的是 。
A)宏替换不占用运行时间B)宏名无类型C)宏替换只是字符替换D)宏名必须用大写字母表示4.在“文件包含”预处理命令形式中,当#include后面的文件名用””(双引号)括起时,寻找被包含文件的方式是 。
A)直接按系统设定的标准方式搜索目录B)先在源程序所在目录中搜索,再按系统设定的标准方式搜索C)仅仅搜索源程序所在目录D)仅仅搜索当前目录5.在“文件包含”预处理命令形式中,当#include后名的文件名用<>(尖括号)括起时,寻找被包含文件的方式是 。
A)直接按系统设定的标准方式搜索目录B)先在源程序所在目录中搜索,再按系统设定的标准方式搜索C)仅仅搜索源程序所在目录D)仅仅搜索当前目录6.在宏定义#define PI 3.1415926中,用宏名PI代替一个 。
A)单精度数B)双精度数C)常量D)字符串7.以下程序的运行结果是 。
#include<stdio.h>#define ADD(x) x+xvoid main ( ){ int m=1,n=2,k=3,sum ;sum = ADD(m+n)*k ;printf(“%d\n”,sum) ;A)9 B)10 C)12 D)188.以下程序的运行结果是 。
#include<stdio.h>#define MIN(x,y) (x)>(y) ? (x) : (y)void main ( ){ int i=10, j=15 , k;k = 10*MIN(i,j);printf(“%d\n”,k);}A)10 B)15 C)100 D)1509.以下程序的运行结果是 。
c#中预处理指令#if的使用c#中预处理指令#if的使用引导语:预处理(pre-treatment),是指在进行最后加工完善以前进行的准备过程,具体应用在不同的行业或领域,会有不同的解释,以下是店铺整理的预处理指令#if的使用,欢迎参考阅读!#if 使您可以开始条件指令,测试一个或多个符号以查看它们是否计算为true。
如果它们的计算结果确实为true,则编译器将计算位于#if 与最近的 #endif 指令之间的所有代码。
例如#define DEBUG// ...#if DEBUGConsole.WriteLine("Debug version");#endif可以使用运算符==(相等)、!=(不相等)、&&(与)及||(或)来计算多个符号。
还可以用括号将符号和运算符分组。
备注使用 #if 以及 #else、#elif、#endif、#define 和 #undef 指令,可以包括或排除基于由一个或多个符号组成的条件的代码。
这在编译调试版本的`代码或编译特定配置时最为有用。
以 #if 指令开始的条件指令必须用 #endif 指令显式终止。
#define 使您可以定义一个符号,通过将该符号用作传递给 #if 指令的表达式,使该表达式计算为 true。
也可以用/define 编译器选项来定义符号。
可以用#undef 来取消定义符号。
用 /define 或 #define 定义的符号与具有同一名称的变量不冲突。
即,不应将变量名传递到预处理器指令,并且只能用预处理器指令计算符号。
用 #define 创建的符号的范围是在其中定义该符号的文件。
示例// preprocessor_if.cs#define DEBUG#define VC_V7using System;public class MyClass{static void Main(){#if (DEBUG && !VC_V7)Console.WriteLine("DEBUG is defined");#elif (!DEBUG && VC_V7)Console.WriteLine("VC_V7 is defined");#elif (DEBUG && VC_V7)Console.WriteLine("DEBUG and VC_V7 are defined");#elseConsole.WriteLine("DEBUG and VC_V7 are not defined"); #endif}}DEBUG and VC_V7 are defined【c#中预处理指令#if的使用】。
第9章预处理命令
宏定义不是C语句,所以不能在行尾加分号。
如果加了分号则会连分号一起进行臵换。
可以用#undef命令终止宏定义的作用域。
对程序中用“”括起来的内容(即字符串内的字符),即使与宏名相同,也不进行臵换。
宏定义只做字符替换,不分配内存空间。
宏名不是变量,不分配存储空间,也不能对其进行赋值。
在宏展开时,预处理程序仅对宏名作简单的字符串替换,不作任何检查。
在进行宏定义时,可以引用已定义的宏名
无参宏定义的一般格式:
#define 标识符字符串
将这个标识符(名字)称为“宏名”,在用预编译时将宏名替换成字符串的过程称为“宏展开”。
#define是宏定义命令。
带参宏定义的一般格式:
#define 宏名(形参表)字符串
带参宏的调用和宏展开:
调用格式:宏名(实参表);
宏展开(又称为宏替换)的方法:用宏调用提供的实参直接臵换宏定义中相应的形参,非形参字符保持不变。
定义有参宏时,宏名与左圆括号之间不能留有空格。
否则,C编译系统会将空格以后的所有字符均作为替代字符串,而将该宏视为无参宏。
有参宏的展开,只是将实参作为字符串,简单地臵换形参字符串,而不做任何语法检查。
为了避免出错,可以在所有形参外,甚至整个字符串外,均加上一对圆括号。
如: #define S(r) 3.14*(r)*(r)
则:area=S(a+b); 展开后为: area=3.14*(a+b)*(a+b);
调用有参函数时,是先求出实参的值,然后再复制一份给形参。
而展开有参宏时,只是将实参简单地臵换形参。
函数调用是在程序运行时处理的,为形参分配临时的内存单元;而宏展开则是在编译前进行的,在展开时不分配内存单元,不进行值的传递,也没有“返回值”的概念。
调用函数只可得到一个返回值,而用宏可以设法得到几个结果。
在有参函数中,形参都是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参和宏名都没有类型,只是一个简单的符号代表,因此,宏定义时,字符串可以是任何类型的数据。
使用宏次数多时,宏展开后源程序变长,因为每展开一次都是程序增长,而函数调用不会使源程序变长。
宏替换不占用运行时间,只占编译时间。
而函数调用则占用运行时间(分配单元、保留现场、值传递、返回)。
在程序中如果有带实参的宏,则按#define命令行中指定的字符串从左到右进行臵换。
如果字符串中包含宏中的形参,则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参。
如果宏定义中的字符串中的字符不是参数字符,则保留。
通常如果调用库函数,则用< >,使用用户自己编写的文件,则用“”。
两种格式的区别仅在于:
⑴使用“”:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定的“包
含文件目录”去查找。
⑵使用< >:直接到系统指定的“包含文件目录”(include)去查找。
预编译时不作任何检查。
只有编译已被宏展开后的源程序时才会发现语法错误并报错。
通常情况下,源程序中所有的行都参加编译,但有时希望对其中一部分内容只在满足一定条件才进行编译,则需要用到条件编译。
(1)一般格式
#ifdef 标识符
程序段1;
#else
程序段2;
#endif
它的作用是若指定的标识符已经被#define命令定义过,则在程序编译阶段编译程序段1,否则,编译程序段2.。
其中,#else部分可以没有。
2)#ifndef 标识符
程序段1
#else
程序段2
#endif
它的作用是若指定的标识符未被#define命令定义过,则在程序编译阶段编译程序段1,否则,编译程序段2.。
(3)#if 表达式
程序段1
#else
程序段2
#endif
它的作用是当指定的表达式的值为真(非零),则在程序编译阶段编译程序段1,否则,编译程序段2.。
(1) 一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个#include 命令。
(2) 如果文件1包含文件2,而在文件2中要用到文件3的内容,则可在文件1中用两个include命令分别包含文件2和文件3,而且文件3应出现在文件2之前,即在file1.c中定义。
(3) 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。
(4) 在#include命令中,文件名可以用双撇号或尖括号括起来。
(5) 被包含文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。
因此,如果file2.h中有全局静态变量,它也在file1.h 文件中有效,不必用extern声明。
如果需要修改程序中常用的一些参数,可以不必修改每个程序,只需将这些参数放在一个头
文件中,在需要是修改头文件即可,但,被包含文件修改后,凡包含此文件的所有文件都要全部重新编译。