C++复习

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

2018-05-30  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读