[开发资料] 单片机的预处理

[复制链接]
61|5
jf101 发表于 2025-10-21 13:47 | 显示全部楼层 |阅读模式
预处理命令可以改变程序设计环境,提高编程效率,它们并不是C语言本身的组成部分,不能直接对它们进行编译,
必须在对程序进行编译之前,先对程序中这些特殊的命令进行“预处理”。经过预处理后,程序就不再包括预处理命令了,
最后再由编译程序对预处理之后的源程序进行编译处理,得到可供执行的目标代码。C语言提供的预处理功能有三种,
分别为宏定义、文件包含和条件编译,下面将对它们进行简单介绍。


 楼主| jf101 发表于 2025-10-21 13:49 | 显示全部楼层
1、宏定义 #define
宏定义在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏”,被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的,宏代换是由预处理程序自动完成的。在C语言中,宏分为有参数和无参数两种。

无参宏的宏名后不带参数,其定义的一般形式为:#define 标识符 字符串; ,“字符串”可以是常数、表达式、格式串等。

常常对程序中反复使用的表达式进行宏定义。例如:

  1. #define M (y*y+3*y);


它的作用是指定标识符M来代替表达式(yy+3y)。在编写源程序时,所有的(yy+3y)都可由M代替,而对源程序进行编译时,将先由预处理程序进行宏代换,即用(yy+3y)表达式去置换所有的宏名M,然后再进行编译。

C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对于带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

带参宏定义的一般形式为:#define 宏名(形参表) 字符串;

带参宏调用的一般形式为:宏名(实参表);

举例:

  1. #include <stdio.h>
  2. #define MAX(a,b) (a>b)?a:b
  3. /*带参数的宏定义*/
  4. main()
  5. {
  6.     int x,y,max;
  7.     printf("input two numbers: ");
  8.     scanf("%d %d",&x,&y);
  9.     max=MAX(x,y);
  10.     printf("max=%d\n",max);
  11.     /*宏调用*/
  12. }


结果如下:

  1. input two numbers: 2009 2010↙
  2. max=2010


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

#define 后面只有一个参数的语法:
一般情况下,宏定义时的用法为:#define a b ,后接两个参数,表示用a代替b。很多时候,#define 后只有一个参数,经常出现在头文件的开始处。

用法解释: 定义宏,并在预处理过程中将其替换为空字符串(即删除)。这样做主要是为了标记某些内容,使程序阅读者能够清楚标记表明的意义,同时又不影响被编译的源代码。也就是说,用法同define后接两个参数一样,只是后一个参数为空字符串。
用途包括:(1)定义一个符号用来给#if(n)def判断。(2)多文件编译中防止头文件被重复包含。

 楼主| jf101 发表于 2025-10-21 13:50 | 显示全部楼层
文件包含 #include
文件包含是C预处理程序的另一个重要功能,文件包含命令行的一般形式为:

#include <文件名> :用尖括号包含头文件,在系统指定的路径下找头文件。

#include "文件名" :用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找。

注意:include 经常用来包含头文件,可以包含 .c 文件,但是大家不要包含.c。因为include 包含的文件会在预编译被展开,如果一个.c 被包含多次,展开多次,会导致函数重复定义。预处理只是对include 等预处理操作进行处理并不会进行语法检查,这个阶段有语法错误也不会报错,第二个阶段即编译阶段才进行语法检查。

一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
 楼主| jf101 发表于 2025-10-21 13:51 | 显示全部楼层
3、条件编译
预处理程序提供了条件编译的功能,可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件,这对于程序的移植和调试是很有用的。条件编译可分为三种形式。

(1)第一种形式如下:

  1. #ifdef 标识符
  2. 程序段 1
  3. #else
  4. 程序段 2
  5. #endif

它的功能是如果 标识符 已被 #define 命令定义过则对 程序段1 进行编译;否则对 程序段2 进行编译。

如果没有程序段2(为空),本格式中的#else可以没有,即可以写为:

  1. #ifdef 标识符
  2. 程序段
  3. #endif


(2)第二种形式如下:

  1. #ifndef 标识符
  2. 程序段 1
  3. #else
  4. 程序段 2
  5. #endif


与第一种形式的区别是将 “ifdef” 改为 “ifndef” 。它的功能是如果 标识符 未被 #define 命令定义过则对 程序段1 进行编译,否则对 程序段2 进行编译。这与第一种形式的功能正好相反。

(3)第三种形式如下:

  1. #if 常量表达式
  2. 程序段 1
  3. #else
  4. 程序段 2
  5. #endif

它的功能是如果常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同的条件下完成不同的功能。

OKAKAKO 发表于 2025-10-22 20:40 | 显示全部楼层
文件包含是C预处理程序的另一个重要功能
AdaMaYun 发表于 2025-10-23 15:01 | 显示全部楼层
预处理其实是很关键的过程
您需要登录后才可以回帖 登录 | 注册

本版积分规则

264

主题

2029

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部