了解C预处理的一些操作,对C的嵌入式开发的设计,调试,应用都会有很大的帮助,因此这里对C预处理器的一些操作做了一个简单的总结,一是对我接下来的嵌入式设计有一个思路的整理,另一方面也希望对偶然逛到本文的你有帮助。
想要深入的了解,必须解决几个问题。
1 . C预处理器负责哪些事情?
1)将符号缩写替换成其表示的内容(ex:#define);
2)包含程序所需的其他文件(ex:#include);
3)选择让编译器查看或者执行哪些代码(#if #else #endif);
2 . 编译器进入预处理之前还会做什么操作?
1)把源码出现的字符映射到源字符集;
这个阶段主要是对程序做字符和字符集的映射操作;
值得注意的是,C语言是基于美键盘而来的,但是有些键盘没有所有C的符号,这个时候怎么办?C提供了三字符序列和双字符序列解决这些问题,因此看到这些代码时,不要觉得奇怪。
例如:
// 三字符序列
??=include <stdio.h>
// 翻译过来就是
#include <stdio.h>
再例如:
// 双字符序列
%:include <stdio.h> //与三字符不同的是,不会替换" "中的双字符序列;
// 翻译过来就是
#include <stdio.h>
2) 编译器定位每个反斜杠后面跟着换行符的实例,并删除他们。 将物理行(physical line)转换成逻辑行(logic line);
#include <stdio.h>
int main()
{
printf("physical line : my name is \ //物理行1 \表示换行
mashuai\r\n"); //物理行2
printf("logical line : my name is mashuai\r\n"); //逻辑行:预处理表达式的基本单位;
}
运行结果为:
physical line : my name is mashuai
logical line : my name is mashuai
3) 编译器将注释用一个空格字符代替。
最后,程序开始准备好进入预处理阶段,预处理将查找一行中以#开始的预处理指令。
3 . 程序预处理是做什么事情?
1)明示常量 #define: 包括一些对象宏和函数宏。 下面列举了一个典型的嵌入式工程宏定义;
值得注意的是,编译器在编译期对所有的常量表达式(只包含常量)求值,所以预处理器不会进行实际的乘除运算。预处理不做计算,不对表达式求值,只是进行简单的替换。
#define U8 unsigned char // 做一些数据结构的定义
#define U16 unsigned short
#define U32 unsigned int
/*宏定义*/
#define FILTERADTIMES 4 // 定义程序运行过程中用到的固定值,便于修正和调试
#define RESADTIMES 8
#define BODYADTIMES 20
#define RESSTABLECOUNT 150
#define BODYSTABLECOUNT 350
#define DEFAULT_KBCOUNT 1100
#define RES_MIN 3000 //200ohm
#define REF_RES 7000 //700ohm
#define RES_MAX 10000 //1500ohm
//#define Short_FWR_50KHz 00110011B // 定义寄存器配置模式,用宏定义更方便阅读和调试;
//#define Ref0_FWR_50KHz 00010011B
//#define Ref1_FWR_50KHz 00100011B
//#define Body_FWR_50KHz 00000011B
#define Short_FWR_50KHz 0x33 //内短模式
#define Ref0_FWR_50KHz 0x13 //参考电阻0模式
#define Ref1_FWR_50KHz 0x23 //参考电阻1模式
#define Body_FWR_50KHz 0x03 //人体模式
/*寄存器地址定义*/
#define ADDR_AFE_SYS 0 // 定义寄存器名,便于程序的阅读和调试;
#define ADDR_AFE_ADC0 1
#define ADDR_AFE_ADC1 2
#define ADDR_AFE_ADC2 3
#define ADDR_AFE_ADC3 4
#define ADDR_AFE_ADC4 5
#define ADDR_AFE_ADC5 6
#define ADDR_AFE_BIM0 7
#define ADDR_AFE_BIM1 8
#define ADDR_AFE_ADO 9
#define ADDR_AFE_ADS 10
#define ADDR_AFE_CONFIG 0x10
#define ADDR_AFE_VREFT 0x11
#define ADDR_AFE_LDOT 0x12
#define ADDR_AFE_OSCT 0x13
#define ADDR_AFE_TST1 0x14
#define ADDR_AFE_TST2 0x15
#define ADDR_AFE_TMUX 0x16
#define ADDR_AFE_OTPCON 0x59
#define ADDR_AFE_TEST 0x5A
#define TOLERANCE0 5 // 定义有固定值通过固定关系衍生出的值,以便于修改和程序调试;
#define Z12_L0 6000-(6000 * TOLERANCE0 / 100)
#define Z12_H0 6000+(6000 * TOLERANCE0 / 100)
#define Z13_L0 5680-(5680 * TOLERANCE0 / 100)
#define Z13_H0 5680+(5680 * TOLERANCE0 / 100)
#define Z14_L0 5680-(5680 * TOLERANCE0 / 100)
#define Z14_H0 5680+(5680 * TOLERANCE0 / 100)
#define Z23_L0 5680-(5680 * TOLERANCE0 / 100)
#define Z23_H0 5680+(5680 * TOLERANCE0 / 100)
#define Z24_L0 5680-(5680 * TOLERANCE0 / 100)
#define Z24_H0 5680+(5680 * TOLERANCE0 / 100)
#endif
2)函数宏:
#include <stdio.h>
#define SQUARE(X) X*X
#define PR(X) printf("The result is %d.\n",X) //函数宏
int main(void)
{
int ex_para=5,ex_result;
ex_result=SQUARE(ex_para);
printf("Evaluating SQUARE(ex_para): %d.\n",ex_result);
printf("Evaluating SQUARE(“#ex_para”): %d.\n",ex_result);
PR(ex_result);
}
// 注意点:这里需要注意的是 函数宏替换时不会替换 "" 内的内容;如果想要替换,就”#ex_para“替换;