预处理指令

简介: 预处理指令
__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

    宏和函数的对比

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

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

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

    宏是没法调试的

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

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

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

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

      • 把宏名全部大写
      • 函数名不要全部大写
      目录
      相关文章
      |
      6天前
      |
      算法 C++ 开发者
      【C/C++ 基础】条件编译相关的预编译指令
      【C/C++ 基础】条件编译相关的预编译指令
      24 0
      |
      11月前
      |
      编译器 C语言
      预处理指令、typedef、条件编译、多文件代码
      预处理指令、typedef、条件编译、多文件代码
      48 0
      |
      C++ 测试技术
      C++ 内置宏定义 与 预编译指令
      内置宏和预编译指令, 在代码调试、单元测试、跨平台代码中经常会用到。这里记录一下。 1. 内置宏 (文件名,当前行号,当前日期,当前时间,当前执行方法名) __FILE____LINE____DATE____TIME__ __FUNCTION__ 2.
      1012 0
      |
      C# 编译器
      C#中的预编译指令介绍
      原文:C#中的预编译指令介绍 1、#define和#undef      用法:           #define DEBUG           #undef DEBUG     #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量,但是它没有具体的值,可以将它看为一个符号而已。
      1097 0
      宏定义
      /* ============================================================================ Name : TestDefine.
      773 0