美文网首页C++复习
C++宏定义(掐小知识点)

C++宏定义(掐小知识点)

作者: 凉拌姨妈好吃 | 来源:发表于2018-05-30 01:37 被阅读5次

    1.宏的各种符号

    1.1关于宏参数里#的知识

    在了解这个小知识点之前,我们先来看看下面这道题

    #define FUN(a) "a"
    FUN(345)

    思考一下现在a会不会被替换成345?
    答案是否定的,""内的字符不能当做形参。那么我们如何才能让它能够替换a?

    #define FUN(a) #a

    . #是字符串化的意思,将a转成一个字符串

    1.2.关于宏参数里##的知识

    把宏参数与宏定义的代码段的标识符连接在一起

    #define Conn(x,y) x##y

    int n = Conn(123,456); /* 结果就是n=123456;*/

    1.3.关于宏参数里#@的知识

    它将单字符标记符变换为单字符,结果返回一个const char类型

    #define ToChar(x) #@x

    char a = ToChar(1);结果就是a='1';


    2.宏替换发生的时间

    源程序在编译的时候经历了预处理、编译、汇编、连接几个过程,而预处理会实现以下几个功能

    1. 文件包含
      这时候会将#include的文件找到并展开到该处。
    2. 条件编译
      预处理器根据#ifdef #if等将源程序的某部分包含进来或排除在外。
    3. 宏展开
      将源程序中有使用到宏的地方展开成相应的宏定义,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能

    3.宏的各种奇妙用法

    3.1 得到一个field在结构体(struct)中的偏移量
    #define OFFSETOF( type, field ) ( (size_t) &(( type *) 0)-> field )
    

    上面的这个宏定义是如何实现的呢?
    我们可以将这个宏分为五个步骤

    1. 0
    2. (type *)0
    3. ((type *)0)->field
    4. &((type *)0)->field
    5. (size_t) &(( type *) 0)-> field
    1. 内存地址从0开始
    2. 将0转为type的结构体指针,也就是说编译器认为这个结构体是开始于程序段起始位置
    3. 引用结构体的field成员
    4. 取该成员的地址
    5. 强转换为size_t
    3.2 得到一个结构体中field所占用的字节数
    #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
    
    3.3 防止溢出的一个方法
    #define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
    
    3.4 防止一个头文件被重复包含
    #ifndef BODYDEF_H
    #define BODYDEF_H
    //头文件内容
    #endif
    

    相关文章

      网友评论

        本文标题:C++宏定义(掐小知识点)

        本文链接:https://www.haomeiwen.com/subject/oivzjftx.html