C语言预处理命令(预处理指令)

C语言预处理命令分为:宏定义、文件包含、条件编译

什么是预处理命令?

预处理命令属于C语言编译器,而不是C语言的组成部分

预处理命令的作用:就是在编译和链接之前,对源文件进行一些文本方面的操作,比如文本替换、文件包含、删除部分代码等,这个过程叫做预处理

预处理命令可以改变程序设计环境,提高编程效率,它们并不是C语言本身的组成部分,不能直接对它们进行编译,必须在对程序进行编译之前,先对程序中这些特殊的命令进行“预处理”。经过预处理后,程序就不再包括预处理命令了,最后再由编译程序对预处理之后的源程序进行编译处理,得到可供执行的目标代码。

(预先处理的部分,在程序进行编译之前运行)

预处理命令的特点:

(1)命令以#开头;

(2)每条命令独占一行;注释可以与指令(命令)放在同一行

(3)命令不以“;”为结束语

功能:

(1)将源文件中以”include”格式包含的文件复制到编译的源文件中。
(2)用实际值替换用“#define”定义的字符串。
(3)根据“#if”后面的条件决定需要编译的代码

工作方式:

预处理的行为是由指令控制的。这些指令是由#字符开头的一些命令。
预处理器的输入是一个C语言程序,程序可能包含指令。预处理器会执行这些指令,并在处理过程中删除这些指令。预处理器的输出是另外一个程序:原程序的一个编辑后的版本,不再包含指令。预处理器的输出被直接交给编译器,编译器检查程序是否有错误,并经程序翻译为目标代码。

宏定义:#define、#undef

什么是宏定义?

在 C 语言源程序中允许用一个标识符来表示一个字符串,称为“”。被定义为“”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。

:宏定义不占内存空间,因为宏在预处理阶段就会被替换掉,到了编译的阶段是没有宏存在的,它在预编译阶段就被处理了

#define:

(无参宏定义)一般形式:

#define 标识符 字符串;

(字符串”可以是常数、表达式、格式串等)

:不管是在某个函数内,还是在所有函数之外(不太建议把#define写在函数内),#define作用域都是从定义开始直到整个文件

带参宏定义:

(带参宏定义)一般形式:

#define 宏名(形参表)  字符串

其中字符串包含各个形参

带参宏定义调用:

带参宏定义调用一般形式:

宏名(实参表);

#include

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void)

{

        printf("Max between 20 and 10 is %d\n", MAX(10, 20));

        return 0;

}

输出结果:Max between 20 and 10 is 20

宏替换相当于实现了一个函数调用的功能,而事实上,与函数调用相比,宏调用更能提高C程序的执行效率

#undef

作用:取消之前的宏定义(也就是#define的标识符)

#undef 标识符

注:如果标识符当前没有被定义成一个宏名称,那么就会忽略该指令

预处理器运算符:宏延续运算符(\)、字符串常量化运算符(#)、标记粘贴运算符(##)

宏延续运算符(\):

一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符(\)。例如:

#define message_for(a, b) \

         printf(#a " and " #b ": We love you!\n")

字符串常量化运算符(#):

在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。

例如:

#include

#define message_for(a, b) \

        printf(#a " and " #b ": We love you!\n")

int main(void)

{

        message_for(Carole, Debra);

         return 0;

}

输出结果:Carole and Debra: We love you!

标记粘贴运算符(##):

宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。

例如:

#include

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void)

{

        int token34 = 40;

        tokenpaster(34);

        return 0;

}

输出结果:token34 = 40

文件包含命令:#include

一般形式:

#include<文件名>

#include"文件名"

区别:头文件的搜索路径不同

尖括号(<>):编译器会到系统路径下查找头文件

(表示在包含文件目录中去查找(包含目录是由系统的环境变量进行设置的,一般为系统头文件的默认存放目录,比如Linux系统在/usr/include目录下),而不在源文件的存放目录中查找)

双引号(""):编译器会先在当前目录下查找头文件,如果没有找到,再到系统路径下查找

(表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找)

功能:

把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。因为有些公用的符号常量或宏定义等可单单独组成一个文件,在其他文件的开头用包含命令包含该文件即可使用。

#include所包含的文件,其扩展名可以是“.c”,表示包含普通C语言源程序。也可以是 “.h”,表示C语言程序的头文件

(1)头文件只能包含变量函数的声明不能包含定义否则在多次引入时会引起重复定义错误

(2)一个include命令只能指定一个被包含头文件,若有多个头文件要包含,则需用多个include命令。

(3)头文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件

什么是头文件?

头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享

有两种类型的头文件:程序员编写的头文件和编译器自带的头文件

引用头文件相当于复制头文件的内容

:在程序中要使用头文件,需要使用 C 预处理指令 #include 来引用它

条件编译:#ifdef、#ifdef...#endef、#ifdef...#else...#endef

预处理程序提供了条件编译的功能,可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件,这对于程序的移植和调试是很有用的。

个人认为条件编译就是判断那个程序段(文件)能否运行

C语言预处理命令(预处理指令)_第1张图片

C语言预处理命令(预处理指令)_第2张图片

 引用:C 预处理器 | 菜鸟教程 (runoob.com)

C 头文件 | 菜鸟教程 (runoob.com)

(11条消息) C语言预处理命令#if、#endif、#undef、#ifdef、#else、#elif——学习总结笔记_#ifdef在哪本书里学到_越吃越胖的黄的博客-CSDN博客

(11条消息) C语言中的预处理详解_c语言预处理是什么意思_BruceZhang的博客-CSDN博客

编译预处理—C语言 - 知乎 (zhihu.com)

C语言宏定义define的用法 - C语言教程 - C语言网 (dotcpp.com)

C语言文件包含include的用法 - C语言教程 - C语言网 (dotcpp.com)

C语言条件编译的用法 - C语言教程 - C语言网 (dotcpp.com)

其他预处理命令 - C语言教程 - C语言网 (dotcpp.com)

你可能感兴趣的:(c语言,c++,学习)