C中的预处理命令
- 格式:docx
- 大小:20.97 KB
- 文档页数:7
c程序的四个基本操作过程
C程序的四个基本操作过程通常指的是预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
这是源代码转化为可执行程序的过程中的四个主要步骤。
1. **预处理**:这一步处理源代码中的预处理指令,比如#include 指令,它会把包含的文件内容插入到程序中。
此外,预处理器还会处理条件编译指令,如#ifdef和#endif,以决定哪些代码段是否应该编译。
2. **编译**:编译器将预处理后的代码转化为汇编语言。
这个阶段会检查语法错误,并生成与源代码对应的汇编代码。
3. **汇编**:汇编器将编译器生成的汇编代码转化为目标文件(通常是.o文件)。
这个阶段会将汇编代码转化为机器语言,但还没有进行链接。
4. **链接**:链接器将所有的目标文件和库文件合并成一个可执行文件。
这个过程包括解决符号引用(例如函数调用),确保所有的依赖关系都得到满足。
以上就是C程序的四个基本操作过程。
在编写和运行C程序时,理解这些步骤是非常重要的,因为它们决定了程序的构建方式和运行效果。
C语言预处理命令之条件编译(#ifdef,#else,#endif,#if等)预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。
可见预处理过程先于编译器对源代码进行处理。
在C语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。
要完成这些工作,就需要使用预处理程序。
尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。
预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。
预处理过程还会删除程序中的注释和多余的空白字符。
预处理指令是以#号开头的代码行。
#号必须是该行除了任何空白字符外的第一个字符。
#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。
整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
下面是部分预处理指令:指令用途#空指令,无任何效果#include包含一个源代码文件#define定义宏#undef取消已定义的宏#if如果给定条件为真,则编译下面代码#ifdef如果宏已经定义,则编译下面代码#ifndef如果宏没有定义,则编译下面代码#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码#endif结束一个#if……#else条件编译块#error停止编译并显示错误信息一、文件包含#include预处理指令的作用是在指令处展开被包含的文件。
包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。
标准C编译器至少支持八重嵌套包含。
预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。
这样就可以在多次包含同一个头文件时,通过给定编译时的条件来达到不同的效果。
例如:#defineAAA#include"t.c"#undefAAA#include"t.c"为了避免那些只能包含一次的头文件被多次包含,可以在头文件中用编译时条件来进行控制。
c语⾔的预处理指令分3种 1宏定义 2条件编译 3⽂件包含宏简介1.C语⾔在对源程序进⾏编译之前,会先对⼀些特殊的预处理指令作解释(⽐如之前使⽤的#include⽂件包含指令),产⽣⼀个新的源程序(这个过程称为编译预处理),之后再进⾏通常的编译所有的预处理指令都是以#开头,并且结尾不⽤分号2.预处理指令分3种 1> 宏定义 2> 条件编译 3> ⽂件包含3.预处理指令在代码翻译成0和1之前执⾏4.预处理的位置是随便写的5.预处理指令的作⽤域:从编写指令的那⼀⾏开始,⼀直到⽂件结尾,可以⽤#undef取消宏定义的作⽤6.宏名⼀般⽤⼤写或者以k开头,变量名⼀般⽤⼩写 宏定义可以分为2种:不带参数的宏定义和带参数的宏定义。
⼀、不带参数的宏定义1.⼀般形式#define 宏名字符串⽐如#define ABC 10右边的字符串也可以省略,⽐如#define ABC2.作⽤它的作⽤是在编译预处理时,将源程序中所有"宏名"替换成右边的"字符串",常⽤来定义常量.3.使⽤习惯与注意1> 宏名⼀般⽤⼤写字母,以便与变量名区别开来,但⽤⼩写也没有语法错误2> 对程序中⽤双引号扩起来的字符串内的字符,不进⾏宏的替换操作。
3> 在编译预处理⽤字符串替换宏名时,不作语法检查,只是简单的字符串替换。
只有在编译的时候才对已经展开宏名的源程序进⾏语法检查4> 宏名的有效范围是从定义位置到⽂件结束。
如果需要终⽌宏定义的作⽤域,可以⽤#undef命令5> 定义⼀个宏时可以引⽤已经定义的宏名#define R 3.0#define PI 3.14#define L 2*PI*R#define S PI*R*R举例1 #include <stdio.h>2#define COUNT 434int main()5 {6char *name = "COUNT";78 printf("%s\n", name);910int ages[COUNT] = {1, 2, 67, 89};1112#define kCount 41314for ( int i = 0; i<COUNT; i++) {15 printf("%d\n", ages[i]);16 }1718// 从这⾏开始,COUNT这个宏就失效19#undef COUNT2021//int a = COUNT 写这个报错2223return0;24 }⼆、带参数的宏定义1.⼀般形式#define 宏名(参数列表) 字符串2.作⽤在编译预处理时,将源程序中所有宏名替换成字符串,并且将字符串中的参数⽤宏名右边参数列表中的参数替换3.使⽤注意1> 宏名和参数列表之间不能有空格,否则空格后⾯的所有字符串都作为替换的字符串2> 带参数的宏在展开时,只作简单的字符和参数的替换,不进⾏任何计算操作。
c语言程序中的预编译命令预编译命令是在编译之前就交由编译器进行相关处理的指令,通常以"#"开头。
预编译命令在整个程序开始编译之前就已经执行。
以下是一些常用的预编译命令:1. #include:用于引入头文件。
例如:```C#include <stdio.h> //引入标准输入输出头文件#include "myheader.h" //引入自定义头文件myheader.h```2. #define:用于定义宏。
例如:```C#define PI 3.14159 //定义宏PI,宏的值是3.14159```3. #undef:用于取消之前定义的宏。
例如:```C#undef PI //取消之前定义的宏PI```4. #ifdef,#ifndef,#endif:用于条件编译。
例如:```C#ifdef PI// 如果宏PI已被定义,则编译以下代码#endif#ifndef PI// 如果宏PI未被定义,则编译以下代码#endif```5. #if, #else, #elif:也是用于条件编译。
例如:```C#if defined(PI)//如果宏PI已被定义,则编译以下代码#else//如果宏PI未被定义,则编译以下代码#endif```6. #error:当某些条件不满足时,输出错误并停止编译。
例如:```C#error "Something went wrong"```7. #pragma:用于实现一些特殊的功能,这个指令和编译器实现有关。
例如:```C#pragma pack(1) //设置结构体的对齐方式为1字节对齐```。
C11标准预处理是指在C语言编程中,使用预处理指令来对源代码进行一些预处理操作。
预处理指令是在编译之前由预处理器处理的指令,它们不是实际的编程语言代码,而是在编译过程中执行的指令。
在C11标准中,常见的预处理指令包括:
1. 宏定义(#define):用于定义宏常量或宏函数。
宏定义可以替换源代码中的标识符为指定的值或代码片段。
2. 头文件包含(#include):用于将一个头文件的内容插入到当前源文件中。
头文件通常包含了一些常用的函数声明、宏定义和类型定义等。
3. 条件编译(#if、#elif、#else、#endif):用于根据条件选择性地编译代码。
通过条件编译指令,可以根据不同的编译选项或编译器设置,选择是否编译特定的代码块。
4. 预定义宏(#defined、#ifdef、#ifndef、#if defined):用于检查某个宏是否被定义或未定义。
这些指令可以用于条件判断和条件编译。
5. 空指令(#pragma):用于向编译器发送特定指令或参数,以控制编译器的行为。
不同的编译器可能支持不同的pragma指令。
预处理指令在编译过程中会被预处理器解析和处理,生成对应的中间代码或目标代码。
预处理指令的使用可以提高代码的可读性、可维护性和可重用性,但也需要谨慎使用,避免出现潜在的问题和错误。
C语⾔的预处理命令前⾔C程序的源代码中可以包含各种编译指令,也被称为预处理命令。
他们实际上不是C语⾔的⼀部分,但却扩展C程序的设计环境。
ANSI标准定义的C语⾔预处理程序包括下列命令:#define,#error,#include,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。
⾮常明显,所有预处理命令均以符号#开头,下⾯分别加以介绍。
#define#define定义了⼀个标识符及⼀个串。
在源程序中遇到该标识符时,都以相应的串代替。
ANSI标准将标识符定义为宏名,将替换过程称为宏替换。
格式⼀般为:#define identifier string注意1. 该语句没有分号。
在在标识符与串之间可以有任意多个空格,串⼀旦开始,仅由⼀新⾏结束。
2. 宏名定义后,即可成为其他宏名定义中的⼀部分。
3. 宏替换仅仅是以⽂本串代替宏标识符,前提是宏标识符必须独⽴的识别出来,否则不进⾏替换。
例如:#define XYZ this is a test使⽤宏printf(“XYZ”)。
该段不打印“this is a test”⽽打印“XYZ”。
因为预编译器识别出的是“XYZ”4. 如果串长于⼀⾏,在该⾏末尾加上\#define LONG_STRING "this is a very long\string that is used as an example"5. 普遍使⽤⼤写字母定义标识符。
6. ⽤宏代换代替实在的函数的⼀⼤好处是宏替换增加了代码的速度,因为不存在函数调⽤的开销。
但增加速度也有代价:由于重复编码⽽增加了程序长度。
#error#error强迫编译程序停⽌编译,主要⽤于程序调试。
#error指令使预处理器发出⼀条错误消息,该指令的作⽤就是在程序崩溃之前给出⼀定的信息。
#include#include使编译程序将另⼀源⽂件嵌⼊带#include的源⽂件,被读⼊的源⽂件必须⽤双引号或尖括号括起来。
c语言的编译流程C语言是一种高级编程语言,被广泛用于系统软件、游戏开发、嵌入式系统等领域。
在使用C语言进行编程时,需要将代码转换为可执行文件,这个过程称为编译。
本文将介绍C语言的编译流程,以及编译过程的主要步骤。
1. 预处理(Preprocessing):编译过程的第一步是预处理,它由预处理器(Preprocessor)执行。
预处理器主要完成以下任务:- 处理以“#”开头的预处理指令,例如#include、#define、#ifdef 等。
- 将所有的#include指令替换为相应的头文件的内容。
-进行宏替换,将程序中的宏定义展开。
- 词法分析(Lexical Analysis):将代码分解为一个个的单词,称为记号(Token)。
- 语法分析(Syntax Analysis):根据语法规则组织单词,并创建语法树(Syntax Tree)。
- 语义分析(Semantic Analysis):对语法树进行分析,检查语义错误,并生成中间代码。
3. 汇编(Assembly):编译器生成的中间代码是与特定平台无关的,需要通过汇编器(Assembler)将其转换为可执行文件。
汇编器主要完成以下任务:-将汇编代码转换为机器码指令。
-将符号名称解析为地址,生成可重定位代码。
4. 链接(Linking):在C语言编程中,通常会使用多个源文件,这些文件中的函数和变量可能相互引用。
链接器(Linker)的作用是将这些文件中的符号引用和定义进行匹配,生成最终的可执行文件。
链接器主要完成以下任务:- 符号解析(Symbol Resolution):将符号引用与符号定义进行匹配。
- 地址重定位(Address Relocation):将代码中的相对地址转换为绝对地址。
- 符号合并(Symbol Merging):将多个源文件中同名的符号进行合并,以解决重复定义的问题。
-生成可执行文件,包括代码段、数据段等。
5. 加载(Loading):加载器(Loader)是操作系统提供的一部分,它将可执行文件加载到内存中,并执行程序。
c语言程序的基本结构C语言是一种广泛应用于计算机编程的高级编程语言,被广泛应用于系统软件、应用软件、嵌入式系统等领域。
了解C语言程序的基本结构对于学习和理解C语言的编程技巧以及写出高效、稳定、易于维护的代码至关重要。
本文将介绍C语言程序的基本结构,以便读者快速上手和编写C语言程序。
一、预处理指令C语言程序通常以预处理指令开始,预处理器会根据这些指令对代码进行预处理,例如移除注释、插入文件等操作。
预处理指令以"#"开头,常见的预处理指令包括:1. #include:用于包含文件,将指定的文件内容插入到当前位置。
例如:`#include <stdio.h>`表示包含标准输入输出头文件。
2. #define:用于定义宏,将一段代码标识为一个宏,并在后续代码中使用。
例如:`#define PI3.14159`定义了一个名为PI的宏,它的值是3.14159。
二、函数声明在C语言程序中,函数是代码的基本组织单元。
函数声明用于向编译器说明函数的名称、参数个数和类型以及返回值类型。
函数声明的语法如下:```返回值类型函数名(参数列表);```例如,以下是一个函数声明的例子:```int add(int a, int b);```三、主函数C语言程序必须包含一个特殊的函数,称为主函数(main函数)。
主函数是程序的入口点,程序在运行时会从主函数开始执行。
主函数的基本结构如下:```返回值类型 main(参数列表) {// 函数体return 0;}```其中,返回值类型通常为int,表示函数执行完成后返回的结果。
参数列表是通过命令行传递给程序的参数,可以为空。
函数体中编写程序的具体逻辑,return语句用于返回结果并结束函数的执行。
```int main() {printf("Hello, World!");return 0;}```四、函数定义函数定义用于给出函数的具体实现。
我们可以在C源程序中插入传给编译程序的各中指令,这些指令被称为预处理器指令,它们扩充了程序设计的环境。
现把常用的预处理命令总结如下:1. 预处理程序按照ANSI标准的定义,预处理程序应该处理以下指令:#if #ifdef #ifndef #else #elif#endif#define#undef#line#error#pragma#include显然,上述所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。
2. #define#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之。
这种标识符称为宏名字,相应的替换称为宏代换。
一般形式如下:#define macro-name char-sequence这种语句不用分号结尾。
宏名字和串之间可以有多个空白符,但串开始后只能以新行终止。
例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:#define LEFT 1#define RIGHT 0每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。
定义一个宏名字之后,可以在其他宏定义中使用,例如:#define ONE 1#define TWO ONE+ONE#define THREE ONE+TWO宏代换就是用相关的串替代标识符。
因此,如果希望定义一条标准错误信息时,可以如下定义:#define ERROR_MS “Standard error on input \n”如果一个串长于一行,可在行尾用反斜线”\”续行,如下:#define LONG_STRING “This is a very very long \String that i s used as an example”3. #error#error指令强制编译程序停止编译,它主要用于程序调试。
#error指令的一般形式是:#error error-message注意,宏串error-message不用双引号包围。
C语⾔预处理命令详解⼀前⾔预处理(或称预编译)是指在进⾏编译的第⼀遍扫描(词法扫描和语法分析)之前所作的⼯作。
预处理指令指⽰在程序正式编译前就由编译器进⾏的操作,可放在程序中任何位置。
预处理是C语⾔的⼀个重要功能,它由预处理程序负责完成。
当对⼀个源⽂件进⾏编译时,系统将⾃动引⽤预处理程序对源程序中的预处理部分作处理,处理完毕⾃动进⼊对源程序的编译。
C语⾔提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(#define)、⽂件包含(#include)、条件编译(#ifdef)等。
合理使⽤预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
本⽂参考诸多资料,详细介绍常⽤的⼏种预处理功能。
因成⽂较早,资料来源⼤多已不可考,敬请谅解。
⼆宏定义C语⾔源程序中允许⽤⼀个标识符来表⽰⼀个字符串,称为“宏”。
被定义为宏的标识符称为“宏名”。
在编译预处理时,对程序中所有出现的宏名,都⽤宏定义中的字符串去代换,这称为宏替换或宏展开。
宏定义是由源程序中的宏定义命令完成的。
宏替换是由预处理程序⾃动完成的。
在C语⾔中,宏定义分为有参数和⽆参数两种。
下⾯分别讨论这两种宏的定义和调⽤。
2.1 ⽆参宏定义⽆参宏的宏名后不带参数。
其定义的⼀般形式为:#define 标识符字符串其中,“#”表⽰这是⼀条预处理命令(以#开头的均为预处理命令)。
“define”为宏定义命令。
“标识符”为符号常量,即宏名。
“字符串”可以是常数、表达式、格式串等。
宏定义⽤宏名来表⽰⼀个字符串,在宏展开时⼜以该字符串取代宏名。
这只是⼀种简单的⽂本替换,预处理程序对它不作任何检查。
如有错误,只能在编译已被宏展开后的源程序时发现。
注意理解宏替换中“换”的概念,即在对相关命令或语句的含义和功能作具体分析之前就要进⾏⽂本替换。
【例1】定义常量:1#define MAX_TIME 1000若在程序⾥⾯写if(time < MAX_TIME){.........},则编译器在处理该代码前会将MAX_TIME替换为1000。
C语言的预处理功能是指 C语言的预处理命令只能实现宏定义和条件编译功能什么是预处理功能在介绍C语言的预处理功能之前,首先我们需要了解什么是预处理功能。
预处理器是C语言的一个重要组成部分,它负责在实际编译之前对源代码进行预处理。
预处理器会对源代码进行一系列的处理,包括宏定义、条件编译、文件包含等等。
C语言的预处理功能是指预处理命令所能实现的功能,其中包括宏定义和条件编译两大主要功能。
宏定义宏定义是C语言中非常重要的一个特性,它使得程序员能够在源代码中定义一些特定的标识符,以便在后续的代码中使用。
宏定义的语法比较简单,一般的格式为 #define 宏名替换文本。
宏定义提供了一种简单且高效的方式来进行代码重用和代码替换。
在预处理阶段,预处理器会根据宏定义的规则将源代码中的宏名替换为对应的替换文本。
宏定义不仅仅可以用来简单的替换文本,在替换文本中还可以使用参数。
这种带有参数的宏定义被称为带参数的宏定义。
带参数的宏定义使得代码更加灵活和可重用。
例如,我们可以定义一个求平方的宏定义,如下所示:#define SQUARE(x) ((x) * (x))在代码中使用宏定义非常简洁,只需要在需要求平方的地方使用宏名即可:int num = 5;int square = SQUARE(num);预处理器会将代码中的 SQUARE(num) 替换为 ((num) * (num)),最终得到的结果是 int square = ((num) * (num));。
条件编译条件编译是C语言预处理功能的另一个重要方面。
条件编译允许程序根据一些条件选择性地编译特定的代码块,从而实现不同平台的适配或者特定条件下的代码执行。
条件编译使用了一些预处理命令,例如 #if、#else、#endif 等等。
条件编译的语法比较灵活,可以根据不同的条件编译不同的代码段。
例如,我们可以使用条件编译来在不同的操作系统下进行适配:#ifdef _WIN32// Windows平台相关代码#else// 非Windows平台相关代码#endif在上述代码中,#ifdef _WIN32 表示如果定义了 _WIN32 这个宏,则编译下方的代码块,否则编译上方的代码块。
C语言预处理器edirective用法C语言预处理器指令(Preprocessor Directive)是一种特殊的指令,它在源代码被编译之前对代码进行预处理。
其中,"directive"是指一种命令,用于告诉编译器在编译过程中进行特定的操作。
预处理器指令在C语言中起到了非常关键的作用,能够使我们在编写程序时更加灵活和高效。
本文将详细介绍C语言预处理器指令的用法和常见示例。
一、预处理器指令的基本语法预处理器指令以"#"字符开始,后跟指令名称和参数(如果有的话)。
预处理器指令通常写在源代码的开头位置,以便在编译器对源代码进行编译之前执行。
例如:```c#include <stdio.h>#define MAX_VALUE 100```其中,"#include"是一种预处理器指令,用于将其他文件的内容包含在当前文件中。
在上述示例中,"<stdio.h>"是一种头文件,它提供了标准输入输出函数的定义。
"#define"是另一种预处理器指令,用于定义一个常量或宏。
二、使用预处理器指令进行文件包含预处理器指令"#include"允许我们在一个文件中包含另一个文件的内容。
这在编写大型程序时非常有用,可以将一些公共的函数或常量定义放在单独的文件中,然后在需要的地方进行引用。
```c#include "utils.h"```在上述示例中,"utils.h"是另一个C语言源文件,其中包含了一些工具函数的定义。
通过使用"#include"指令,我们可以在当前文件中引用该文件,并且可以直接使用其中定义的函数。
三、使用预处理器指令进行常量和宏定义预处理器指令"#define"用于定义常量和宏。
常量是在程序中不可改变的值,而宏是一种用代码替换的方式。
C中的预处理命令是由ANSIC统一规定的,但它不是C语言的本身组成部分,不能直接对它们进行编译,因为编译程序无法识别它们。
必须对程序进行通常的编译(包括词法和语法分析,代码生成,优化等)之前,先对程序中这些特殊的命令进行“预处理”,例如:如果程序中用#include命令包含一个文件“stdio.h”,则在预处理时,将stdio.h文件中的实际内容代替该命令。
经过预处理后的程序就像没有使用预处理的程序一样干净了,然后再由编译程序对它进行编译处理,得到可供执行的目标代码。
现在的编译系统都包括了预处理,编译和连接部分,在进行编译时一气呵成。
我们要记住的是预处理命令不是C语言的一部分,它是在程序编译前由预处理程序完成的。
C提供的预处理功能主要有三种:宏定义,文件包含,条件编译。
它们的命令都以“#”开头。
一,宏定义:用一个指定的标识符来代表一个字符串,它的一般形式为:#define 标识符字符串#define PI 3.1415926我们把标识符称为“宏名”,在预编译时将宏名替换成字符串的过程称为“宏展开”,而#define 是宏定义命令。
几个应该注意的问题:1,是用宏名代替一个字符串,也就是做简单的置换,不做正确性检查,如把上面例子中的1写为小写字母l,预编译程序是不会报错的,只有在正式编译是才显示出来。
2,宏定义不是C语句,不必在行未加分号,如果加了分号则会连分号一起置换。
3,#define语句出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束,通常#define命令写在文件开头,函数之前,作为文件的一部分,在此文件范围内有效。
4,可以用#undef命令终止宏定义的作用域。
如:#define PI 3.1415926main(){}#undef PImysub(){}则在mysub中PI 不代表3.1415926。
5,在进行宏定义时,可以引用已定义的宏名,可以层层置换。
6,对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。
7,宏定义是专门用于预处理命令的一个专有名词,它与定义变量的含义不同,只做字符替换不做内存分配。
带参数的宏定义,不只进行简单的字符串替换,还进行参数替换。
定义的一般形式为:#define 宏名(参数表)字符串如:#define S(a,b) a*b,具体使用的时候是int area; area=(2,3);对带参数的宏定义是这样展开置换的:在程序中如果有带参数的宏(如area=(2,3)),则按#define命令行中指定的字符串从左到右进行置换。
如果串中包含宏中的形参(如a,b),则将程序语句中的相关参数(可以是常量,变量,或表达式)代替形参。
如果宏定义中的字符串中的字符不是参数字符(如上*),则保留,这样就形成了置换的字符串。
带参数的宏与函数有许多相似之处,在调用函数时也是在函数名后的括号内写实参,也要求实参与形参的数目相等,但它们之间还有很大的不同,主要有:1,函数调用时,先求出实参表达式的值,然后代入形参,而使用带参的宏只是进行简单的字符替换。
2,函数调用是在程序运行时处理的,为形参分配临时的内存单元。
而宏展开则是在编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有返回值的概念。
3,对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时代入指定的字符串即可。
宏定义时,字符串可以是任何类型的数据。
4,函数调用只可得到一个返回值,而用宏可以设法得到几个结果。
5,使用宏次数多时,宏展开后源程序长,因为没展开一次都使程序增长,而函数调用不会这样。
6,宏替换不占运行时间,只占编译时间,而函数调用则占运行时间(分配单元,保留现场,值传递,返回)。
二,文件包含:一个源文件可以将另一个源文件的全部内容包含进来,即将另外的文件包含到本文件中。
#include <文件名> 或#include“文件名”感觉它像JAVA中的包,而它的作用像在J2EE中我们可以用*.xml做配置文件,然后各个模块调用这个文件,但这个文件如果修改后,凡使用(包含)此文件的所有文件(因为使用时是拷贝了原来的一份)有都需要从新编译,好像又失去了灵活的意义。
在#include命令中,文件名可以用“”或<>括起来,它们的区别是用<>时,系统到存放在用户当前目录中寻找要包含的文件,若找不到,再按照标准方式查找(即按尖括号的方式查找)。
一般说来,如果是为调用库函数而用#include命令来包含相关的头文件,则用<>,以节省查找时间。
如果要包含的是用户自己编写的文件(这种文件一般都在当前目录中),一般用“”,若文件不在当前目录中,“”内可给出文件路径。
三,条件编译一般情况下,源程序中的所有行都参加编译。
但有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是条件编译。
1,#indef 标识符程序段1#else程序段2#endif当所指定的标识符已经被#include命令定义过,则在程序编译阶段只编译程序1,否则编译程序段2。
2,#if 表达式程序段1#else程序段2#endif优点:采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间,当条件编译段比较多时,目标程序长度可大大减少。
预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。
可见预处理过程先于编译器对源代码进行处理。
在C语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。
要完成这些工作,就需要使用预处理程序。
尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。
预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。
预处理过程还会删除程序中的注释和多余的空白字符。
预处理指令是以#号开头的代码行。
#号必须是该行除了任何空白字符外的第一个字符。
#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。
整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
下面是部分预处理指令:指令用途# 空指令,无任何效果#include 包含一个源代码文件#define 定义宏#undef 取消已定义的宏#if 如果给定条件为真,则编译下面代码#ifdef 如果宏已经定义,则编译下面代码#ifndef 如果宏没有定义,则编译下面代码#elif 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码#endif 结束一个#if……#else条件编译块#error 停止编译并显示错误信息一、文件包含#include预处理指令的作用是在指令处展开被包含的文件。
包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。
标准C编译器至少支持八重嵌套包含。
预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。
这样就可以在多次包含同一个头文件时,通过给定编译时的条件来达到不同的效果。
例如:#define AAA#include "t.c"#undef AAA#include "t.c"为了避免那些只能包含一次的头文件被多次包含,可以在头文件中用编译时条件来进行控制。
例如:/*my.h*/#ifndef MY_H#define MY_H……#endif在程序中包含头文件有两种格式:#include <my.h>#include "my.h"第一种方法是用尖括号把头文件括起来。
这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。
第二种方法是用双引号把头文件括起来。
这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件,如果找不到,再搜索编译器自带的头文件。
采用两种不同包含格式的理由在于,编译器是安装在公共子目录下的,而被编译的应用程序是在它们自己的私有子目录下的。
一个应用程序既包含编译器提供的公共头文件,也包含自定义的私有头文件。
采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。
二、宏宏定义了一个代表特定内容的标识符。
预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。
宏最常见的用法是定义代表某个值的全局符号。
宏的第二种用法是定义带参数的宏,这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。
1.#define指令#define预处理指令是用来定义宏的。
该指令最简单的格式是:首先神明一个标识符,然后给出这个标识符代表的代码。
在后面的源代码中,就用这些代码来替代该标识符。
这种宏把程序中要用到的一些全局值提取出来,赋给一些记忆标识符。
#define MAX_NUM 10int array[MAX_NUM];for(i=0;i<MAX_NUM;i++) /*……*/在这个例子中,对于阅读该程序的人来说,符号MAX_NUM就有特定的含义,它代表的值给出了数组所能容纳的最大元素数目。
程序中可以多次使用这个值。
作为一种约定,习惯上总是全部用大写字母来定义宏,这样易于把程序红的宏标识符和一般变量标识符区别开来。
如果想要改变数组的大小,只需要更改宏定义并重新编译程序即可。
宏表示的值可以是一个常量表达式,其中允许包括前面已经定义的宏标识符。
例如:#define ONE 1#define TWO 2#define THREE (ONE+TWO)注意上面的宏定义使用了括号。
尽管它们并不是必须的。
但出于谨慎考虑,还是应该加上括号的。
例如:six=THREE*TWO;预处理过程把上面的一行代码转换成:six=(ONE+TWO)*TWO;如果没有那个括号,就转换成six=ONE+TWO*TWO;了。
宏还可以代表一个字符串常量,例如:#define VERSION "Version 1.0 Copyright(c) 2003"2.带参数的#define指令带参数的宏和函数调用看起来有些相似。
看一个例子:#define Cube(x) (x)*(x)*(x)可以时任何数字表达式甚至函数调用来代替参数x。
这里再次提醒大家注意括号的使用。
宏展开后完全包含在一对括号中,而且参数也包含在括号中,这样就保证了宏和参数的完整性。
看一个用法:int num=8+2;volume=Cube(num);展开后为(8+2)*(8+2)*(8+2);如果没有那些括号就变为8+2*8+2*8+2了。