预处理指令

简介: 预处理指令
__FILE__
__LINE__
__DATE__
__TIME__
__STDC__
//进行编译的源文件
//文件当前的行号
//文件被编译的日期
//文件被编译的时间
//如果编译器遵循ANSI C,其值为1,否则未定义

这些都是C语言内置的预处理符号。

image.png

所有的预处理指令都会在代码的预处理阶段被替换。

image.png

  #define

语法:

#define name stuff

#define除了可以定义标识符之外还可以定义宏

下面是宏的申明方式:

#define name( parament-list ) stuff

例如:

#define MAX(x, y) (x)>(y)?(x):(y)

image.gif

而宏的调用和函数是一样的

image.gif编辑

但是函数是传值宏是替换

#define的替换规则:

    • 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
    • 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
    • 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程
    • 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
    • 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

    这里有一点需要特别注意不然非常容易出错,因为宏是直接进行替换的如图,

    image.png

    可是函数是先计算出一个值然后将值拷贝过去所以如果传的参是一个表达式那么宏的出错率要远远高于函数。比如下面这个我们的初心是计算4*4=16,可是因为宏的特性程序实际计算的是3+1*4=7;而函数的结果就非常容易预估了。

    image.png

    所以在定义宏时应该注意:

    • 不要吝啬括号最好对每个变量都使用;
    • 因为宏不方便调试所以计量不要将宏定义的过于复杂。

    #和##

    平时的使用中如果我们运行下面的代码,我们想让输出结果随着变量名的改变而改变比如把a改为b输出结果就变为b=10,这在函数中是无论如何都不会实现的:

    image.png

    这时就要使用#了

    image.png

    可以看到在宏中使用’#‘符号就可以做到。

    而如果在宏中使用‘##’就可以将两个字符串进行合并。

    image.png

     条件编译

    #if 常量表达式//常量表达式由预处理器求值
    //...
    #endif
    多个分支的条件编译
    #if 常量表达式
    //...
    #elif 常量表达式
    //...
    #else
    //...
    #endif
    判断是否被定义
    #if defined(symbol)
    //可以缩写为:
    #ifdef symbol
    #if !defined(symbol)
    //可以缩写为:
    #ifndef symbol

    image.gif

    宏和函数的对比

    因为宏省去了函数调用和返回的时间所以宏的速度更快

    函数的参数必须声明为特定的类型所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于>来比较的类型。宏是类型无关的

    每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度

    宏是没法调试的

    宏由于类型无关,也就不够严谨

    宏可能会带来运算符优先级的问题,导致程容易出现错

    一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。

    那我们平时的一个习惯是:

      • 把宏名全部大写
      • 函数名不要全部大写
      目录
      相关文章
      |
      Shell
      在Bash中检查变量是否为空的几种方法
      在Bash中检查变量是否为空的几种方法
      1764 0
      在Bash中检查变量是否为空的几种方法
      |
      网络安全 Apache
      Apache服务器安装SSL证书
      Apache服务器安装SSL证书
      430 0
      |
      JavaScript
      搭建Vue3组件库:第四章 使用Vitepress搭建文档网站
      文档建设一般会是一个静态网站的形式 ,这次采用 Vitepress 完成文档建设工作。 Vitepress 是一款基于Vite 的静态站点生成工具。开发的初衷就是为了建设 Vue 的文档。Vitepress 的方便之处在于,可以使用流行的 Markdown 语法进行编写,也可以直接运行 Vue 的代码。也就是说,它能很方便地完成展示组件 Demo 的任务。
      2005 0
      搭建Vue3组件库:第四章 使用Vitepress搭建文档网站
      |
      存储 人工智能 安全
      JWT的详细讲解-- AI比我们呢更了解JWT(PS: 此文由AI生成)
      JWT的详细讲解-- AI比我们呢更了解JWT(PS: 此文由AI生成)
      515 0
      |
      存储 API 文件存储
      对象存储、块存储、文件存储他们都有什么不通的作用?
      对象存储、块存储、文件存储他们都有什么不通的作用?
      637 0
      |
      数据可视化 C# Python
      C#基于ScottPlot进行可视化
      C#基于ScottPlot进行可视化
      186 1
      |
      jenkins Java 持续交付
      jenkins学习笔记之十九:Docker安装jenkins master及动、静态配置slave
      jenkins学习笔记之十九:Docker安装jenkins master及动、静态配置slave
      vscode——Todo Tree
      vscode——Todo Tree
      224 0
      |
      缓存
      ARM学习扫盲篇(一):CPSR&SPSR、Lcache&Dcache、w/parity&w/ECC
      ARM学习扫盲篇(一):CPSR&SPSR、Lcache&Dcache、w/parity&w/ECC
      266 0
      |
      传感器 安全 Go
      程序与技术分享:3D打印机如何添加自动调平功能
      程序与技术分享:3D打印机如何添加自动调平功能
      431 0