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

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

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

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

#define定义宏

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

系统提供的预定义宏

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

条件编译

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

#undef取消已定义的宏

带参数的宏

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

*字符串常量化(#)

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

宏换行(\)

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

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

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

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

C语言讲义——预处理的更多相关文章

  1. C语言: 预处理

    1. 字符映射 键盘有多种标准规格,例如常用的IBM 104键盘标准,然而不是所有键盘都能打出像#这样的符号,因此C语言的预处理引入了字符映射机制.如果程序员要求,预处理会按照约定对源代码中的字符进行 ...

  2. C语言之预处理命令

    /**************************************************************************** Title:C之预处理命令 Time:201 ...

  3. R语言数据预处理

    R语言数据预处理 一.日期时间.字符串的处理 日期 Date: 日期类,年与日 POSIXct: 日期时间类,精确到秒,用数字表示 POSIXlt: 日期时间类,精确到秒,用列表表示 Sys.date ...

  4. C语言之预处理详解

    C语言之预处理详解 纲要: 预定义符号 #define #define定义标识符 #define定义宏 #define的替换规则 #与## 几点注意#undef 带副作用的宏参数 宏和函数的对比 命名 ...

  5. C语言之预处理

    这是2016年的最后一篇博客,年初定的计划是写12篇博客,每月一篇,1/3转载,2/3原创,看来是实现不了了! -- 题外话.今天要写的东西是C语言中的预处理器,我们常说的宏定义的用法.为什么要写这个 ...

  6. iOS开发系列--C语言之预处理

    概述 大家都知道一个C程序的运行包括编译和链接两个阶段,其实在编译之前预处理器首先要进行预处理操作,将处理完产生的一个新的源文件进行编译.由于预处理指令是在编译之前就进行了,因此很多时候它要比在程序运 ...

  7. Linux C编程学习之C语言简介---预处理、宏、文件包含……

    C的简介 C语言的结构极其紧凑,C语言是一种模块化的编程语言,整个程序可以分割为几个相对独立的功能模块,模块之间的相互调用和数据传递是非常方便的 C语言的表达能力十分强大.C语言兼顾了高级语言和汇编语 ...

  8. 【C语言入门教程】2.8 C 语言的预处理命令

    预处理命令是在程序编译阶段进行执行的命令,用于编译与特定环境相关的可执行文件.预处理命令扩展了 C 语言,本节将选择其中一些常用的预处理命令进行讲解. 2.8.1 宏替换命令 宏替换命令的作用类似于对 ...

  9. c语言编译预处理和条件编译执行过程的理解

    在C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令.预处理命令属于C语言编译器,而不是C语言的组成部分.通过预处理命令可扩展C语言程序设计的环境. 一.预处理的工作方式 1.1. ...

随机推荐

  1. Redis---07主从复制(哨兵模式)

    一.什么是哨兵模式 基于主从复制的一般模式(一主二从)下,当发生主机发生宕机时,会通过流言协议判断主机是不是宕机,是的话则会通过投票协议自动把某一个从机转换成主机. 二.设置哨兵模式的配置文件 通过r ...

  2. Go module 本地导包方式

    tip本文只讲关于Go module 本地导包方式,其他请自行查阅 Go module 导包方式,go mod init project-name,会得到一个go.mod文件,此文件是管理依赖的,通常 ...

  3. oracle基本学习

    oracle目录及卸载 1.oracle的目录介绍: oradata:数据库存储文件的目录 db_home: network >admin:配置网络服务和监听器服务 jdk:oracle自带jd ...

  4. Redis缓存雪崩和穿透的解决方法

    转载自: https://blog.csdn.net/qq_35433716/article/details/86375506 如何解决缓存雪崩?如何解决缓存穿透?如何保证缓存与数据库双写时一致的问题 ...

  5. 删除指定路径下指定天数之前(以文件的最后修改日期为准)的文件:BAT + VBS

    代码如下: @echo off ::演示:删除指定路径下指定天数之前(以文件的最后修改日期为准)的文件. ::如果演示结果无误,把del前面的echo去掉,即可实现真正删除. ::本例调用了临时VBS ...

  6. 双十一,就用turtle画个单身狗送给自己

    今年的双十一到了 但还有谁记得双十一是 单身狗的节日 单身狗的我是时候站出来 捍卫自己的权益了 单身是一种怎样的状态? 我们所有人都单身过,但也许只有很少的人真正体验过. 短视频内容完全是假的,全程是 ...

  7. Electron入门指北

    最近几年最火的桌面化技术,无疑是Qt+和Electron. 两者都有跨平台桌面化技术,并不局限于Windows系统.前者因嵌入式而诞生,在演变过程中,逐步完善了生态以及工具链.后者则是依托于Node. ...

  8. 内网渗透 day4-meterpreter基本命令

    meterpreter基本命令 目录 1.getuid 查看当前用户 1 2.getpid 查看当前的进程id 1 3.getsystem 初步提权 1 4.ps 1.查看进程列表2.帮助我们获取pi ...

  9. C语言I博客作业3

    这个作业属于哪个课程 <https://edu.cnblogs.com/campus/zswxy/SE2020-1 > 这个作业要求在哪里 https://edu.cnblogs.com/ ...

  10. 华为+京东数科(原京东金融)面经--Java后台开发

    华为: 1.笔试中遇到的问题,如何解决的?(Scanner 如何结束循环读取数据,笔者在面试中因没有理解到Scanner类的hasNext()与hasNextLine()是阻塞方法,导致没有正确退出循 ...