C预处理器是一个文本替换工具,在实际编译之前完成一些预先的处理。

C预处理器(C Preprocessor)简写为 CPP

预处理器命令都是以#开头,如:

#include <stdio.h>
包含源代码文件stdio.h

#define定义宏

  1. 代码文本替换
  2. 增强可读性
#define MAX_ARRAY_LENGTH 20
main () {
/*
*把所有的MAX_ARRAY_LENGTH 替换为20
*#define:增强可读性
*/
char a1[MAX_ARRAY_LENGTH];
char a2[MAX_ARRAY_LENGTH];
char a3[20];
}

系统提供的预定义宏

DATE 当前日期 字符串常量
TIME 当前时间 字符串常量
FILE 当前文件名 字符串常量
LINE 当前行号 十进制数字常量
puts(__DATE__);
puts(__TIME__);
puts(__FILE__);
printf("%d",__LINE__);

条件编译

  • 定义一个非0的宏
#include <stdio.h>
#define DEBUG 1
main(void) {
#if DEBUG
printf("Debug模式");
#else
printf("Release模式");
#endif
}
  • defined:专用于预处理器的运算符,只要定义无需具体内容
#include <stdio.h>
#define DEBUG
main(void) {
#if defined(DEBUG)
printf("Debug模式");
#else
printf("Release模式");
#endif
}

#undef取消已定义的宏

带参数的宏

  • 带参数的宏经常用来作为简单的函数使用。
  • 宏名字和左括号间必须没有空格。
  • 比函数速度稍微快一些(函数需要存储上下文信息、复制参数值等)。
  • 宏参数没有类型,更通用。
  • 每次调用宏都有代码替换,编译后代码会变大。
#include <stdio.h>
#define MAX(x,y) (x>y?x:y)
main(void) {
int i = MAX(1,2);
// →int i = (1>2?1:2);
printf("%d",i);
}
#include <stdio.h>
#define IS_EVEN(n) (n%2==0)
main(void) {
int i = IS_EVEN(20);
// →int i = (20%2==0);
printf("%d\n",i);
int j = IS_EVEN(21);
// →int i = (21%2==0);
printf("%d\n",j);
}

*字符串常量化(#)

#include <stdio.h>
#define func(a) printf("我乃是")
int main(void) {
func("五百年前大闹天宫的齐天大圣");
return 0;
}
#include <stdio.h>
#define func(a) printf("我乃是"#a)
int main(void) {
func(五百年前大闹天宫的齐天大圣);
return 0;
}

宏换行(\)

#include <stdio.h>
#define func(a) \
printf("我乃是"#a)
int main(void) {
func(五百年前大闹天宫的齐天大圣);
return 0;
}

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

  • 将两个标记“粘合”在一起。

    如:MAX函数,只能用于某一特定的类型,如果既要适用于int,又要适用于float,就需要定义两个函数,函数体完全一样。如果还要再适用于long,double等,重复代码将会更多。
#include <stdio.h>
int int_max(int x,int y) {
return x>y?x:y;
}
float float_max(float x,float y) {
return x>y?x:y;
}
main(void) {
printf("%d\n",int_max(1,2));
printf("%f\n",float_max(1.2,2.3));
}
#include <stdio.h>
#define GENERIC_MAX(t) \
t t##_max(t x,t y)\
{\
return x>y?x:y;\
}
GENERIC_MAX(int);
GENERIC_MAX(float);
main(void) {
printf("%d\n",int_max(1,2));
printf("%f\n",float_max(1.2,2.3));
}

最新文章

  1. XML 动态 插入 父类标示 子类标示
  2. mybatis,Spring等工具对xml文件正确性的验证
  3. EJB的调用
  4. OutputDebugString()
  5. jeasyUI属性列表
  6. 定位- CLGeoencoder - 反编码
  7. (转)回车 执行button点击
  8. GO的MAP字典简单用法示例
  9. js实现存储对象的数据结构hashTable和list
  10. python3之微信文章爬虫
  11. css3新属性的学习使用
  12. sed插入,替换指定行的特定字符串,删除指定行首的#
  13. [Oracle][Metadata]如何查找与某一个功能相关的数据字典名
  14. AC自动机自我理解和模板
  15. [UE4]Set Array Elem
  16. sql点滴43—mysql允许用户远程登陆
  17. Unified Modeling Language
  18. (转)PlayerPrefs游戏存档
  19. Servlet映射规范和隐式映射
  20. git使用笔记(十三)ls-files

热门文章

  1. 想买保时捷的运维李先生学Java性能之 垃圾收集算法
  2. day79:luffy:注册之对手机号的验证&amp;实现基本的注册功能逻辑&amp;点击获取验证码&amp;redis
  3. 如何学习C语言
  4. 使用java动态字节码技术简单实现arthas的trace功能。
  5. Group指定的方式如下: @Test(groups = {&quot;fast&quot;, &quot;unit&quot;, &quot;database&quot; })
  6. z-index属性详解
  7. 为研发同学定制的MySQL面试指南 - “能谈谈基数统计吗?”
  8. MYSQL的添加字段和修改字段
  9. 利用Kotlin扩展函数实现任意View的点击处理(点击效果和防止快速点击)
  10. map,filter