编译预处理笔记
个人学习随笔,仅做学习之用
1)类型
i)宏定义 #define
ii)头文件包含 #include
iii)条件编译 #if 0 #endif
iv)打印错误信息 #error
2)格式
i)以“#”开头,预处理标识
ii)单独书写一行
iii)没有分号做结尾
【1】宏定义
#define #undef
不做语法检查,只是简单的替换。
注意:宏定义是简单的替换,不占内存空间。
格式:
#define <宏名> <宏体>
宏名:一般大写
宏体:可以省略,如果省略,就代表这个宏在别的地方定义过。
1)无参宏定义
#define N 10
#define N
#define STR "1234567890"
#define STR1 "123456789012345678901234567890\ //如果语句太长,可以用'\'进行换行。
1234567890"
2)带参宏定义 可以做简单的计算,替换简单的函数
#define MAX(a,b) (a)>(b)?(a):(b) //在宏体部分,ab表达式最好加上(),因为宏只做简单替换
#define MUL(a,b) (a)*(b)
3)#undef 取消宏定义
格式:
#undef 宏名
例子:
#define N 10
#undef N
宏定义的有效范围:
1)如果没有#undef,整个.c文件
2)如果有#undef,从 #define 到 #undef
【2】头文件包含
#include <stdio.h> :从标准库目录中查找头文件 /usr/include
#Include "fun.h" :从指定目录查找头文件,如果没有查到,就到标准库目录中查找
【3】条件编译
1)#if - #elif - #else - #endif
#if 常量
#endif
注意:
i)#if和#endif是成对出现的,有#if一定有#endif
ii)#if后面必须跟常量,无参宏定义,不能是变量
#define STM32 0
#define DAHUA 0
#define HAISI 1
#if STM32
//stm32初始化
printf("stm32\n");
#elif DAHUA
//dahua初始化
printf("DAHUA\n");
#else
//HAISI初始化
printf("HAISI\n");
#endif
2)#ifndef #ifdef #endif
#ifndef :如果没有宏定义
#ifdef :如果宏定义了
通常用于头文件书写,防止头文件重复包含
【4】打印错误信息 #error
无论是否有实际错误,#error命令都会让预处理器发出错误消息
格式:
#error "错误文本信息"
#ifndef TEST
#error "22222222"
#endif
【5】辅助调试的宏
__LINE__ 打印行号;
__FUNCTION__ 打印函数名;
__func__ 打印函数名;
__FILE__ 打印文件名;
printf("%d %s %s\n", __LINE__, __func__, __FILE__);
【6】以定义一个不易发生错误的内存分配器举例
alloc.h
/*定义个不易发生错误的内存分配器alloc.h*/
#include <stdlib.h>
#define malloc //不要直接使用malloc
/*
用于防止由于其他代码块直接塞入程序而导致的偶尔直接调用malloc的行为,增加这个指令以后,
如果程序偶尔调用了malloc,程序将由于语法错误而无法编译,
在alloc中必须加入#undef指令,这样才能调用malloc而不至于出错。
*/
#define MALLOC(num,type)(type*)alloc((num)*sizeof(type))
extren void *alloc(size_t size); //extern冗余
/*不易发生错误的内存分配器的实现alloc.c*/
#include <stdio.h>
#include "alloc.h"
#undef malloc
void *alloc(size_t size){
void *new_mem;
/*请求所需的内存,并检查确实分配成功*/
new_mem = malloc(size);
if(new_mem == NULL){
printf("out of memory!");
exit(1);
}
return new_mem;
}
/*一个使用很少引起错误的内存分配器的程序a_client.c*/
#include "alloc.h"
void function(){
int *new_memory;
/*获得一串整型空间*/
new_memory = MALLOC(25,int);
}