预编译指令
#define //宏定义命名,定义一个标识符来表示一个常量
#include //文件包含命令,用来引入对应的头文件或其他文件
#undef //来将前面定义的宏标识符取消定义
#ifdef //条件编译
#ifndef //条件编译
#if //条件编译
#else //条件编译
#elif //条件编译
#endif //条件编译
#error //用于生成一个编译错误消息
__DATE__ //当前日期,一个以 “MMM DD YYYY” 格式表示的字符串常量
__TIME__ //当前时间,一个以 “HH:MM:SS” 格式表示的字符串常量。
__FILE__ //这会包含当前文件名,一个字符串常量。
__LINE__ //这会包含当前行号,一个十进制常量。
__STDC__ //当编译器以 ANSI 标准编译时,则定义为 1;判断该文件是不是标准 C 程序。
特殊符号
预编译程序可以识别一些特殊符号。预编译程序对于在源程序中出现的这些特殊符号将用合适的值进行替换。这些特殊符号包括:__DATE__、 __TIME__、__FILE__、 __LINE__、 __STDC__。注意,是双下划线,而不是单下划线 :
__FILE__包含当前程序文件名的字符串;__LINE__表示当前行号的整数;__DATE__包含当前日期的字符串;__STDC__如果编译器遵循ANSI C标准,它就是个非零值;__TIME__包含当前时间的字符串。
#include<stdio.h>
int main()
{
printf("Hello World!\n");
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__);
printf("%d\n", __TIME__);
printf("%d\n", __STDC__);
return 0;
}
#和##
字符串化运算符#将宏参数转换为字符串文本;标记粘贴运算符##把两个参数粘贴在一起,其含义就是粘贴之后所形成标识符的定义。如下例子1,定义了一个带参数的宏paster(n),在调用paster(9);后,宏展开为printf_s( "token" #9 " = %d", token##9 );,#9的含义为字符串"9",token##9的含义为token9,其是一个标识符,类型为int,值为9。如下例子2#define STR(s) #s,利用#可以很轻松定义出一个字符串转换函数。
/*例子1*/
#include <stdio.h>
#define paster(n) printf_s( "token" #n " = %d", token##n )
int token9 = 9;
int main()
{
paster(9); //输出:token9 = 9
}
/*例子2*/
#define STR(s) #s // 字符串转换
多行宏定义的使用
\是续行操作符,也就是宏定义一行写不完,需要多行写,就需要在每一行的后面加上续行操作符,注意字符\后要紧跟回车键,中间不能有空格或其他字符。
#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOCEN);\
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOCEN);\
UNUSED(tmpreg); \
} while(0)