预定义 宏 #define 详解

前言:

编译一个程序涉及很多的步骤

第一个就是预处理阶段
预处理器就是在源码编译之前进行一些文本性质的操作
主要任务比如: 删除注释,插入被include 包含的头文件的内容,替换由define定义的符号,以及确认根据
条件编译进行编译

预定义的符号

这些都是被占用的预定义的

符号样例值含义
__ FILE __XXX.CPP进行编译的源文件的名字
__ LINE __30文件当前的行号
__ DATE __Jan 32 1997文件被编译的日期
__ TIME __12:00:00文件被编译的时间

还有一些预定义宏

#define 机制包括一个允许把参数替换到文本中 ,这种规定成为 宏

#deine name(parameter-list)  stuff

注意: 这个parameter-list 参数列表,是由逗号分隔的列表 它的左括号必须与name 紧挨,否则被认为是
stuff 的一部分

我们定义一个宏 实现开方

#define SQUARE(x)	x*x

SQUARE(5)

这时预处理器就会把这个替换为  5*5

看下面的代码

坑(一)
int a = 5;

SQUARE(a+1)

等于 6*6 = 36 ??

错误

仔细看 被转换为

(5+1 * 5+1)

结果为:11 

是不是有坑

我们改为

#define SQUARE(x)	(x)*(x)

这样就ok了


坑(二)
定义一个宏

#define DOUBLE(x)	(x)+(x)

int a  = 10 * DOUBLE(5);

会出现什么结果? 20吗?

错误

展开宏

10 * (5) + (5)

结果为: 55

所以我们还要在表达式两边加个括号

#define DOUBLE(X)	((X) + (X))

这样就ok 了

宏与函数的对比

宏非常频繁的用于执行简单的计算比如 比大小

#define MAX(a,b)	((a) > (b) ? (a) : (b))

为什么不用函数呢?

第一 函数的代码写起来要比宏的代码量要大
第二 用宏在执行小型的代码量时速度要比函数快
第三 如果不用模板写法 函数参数必须要指定参数类型,而 宏 double int float 都可以传入

这些优点都要建立在 宏定义非常短的前提下

带副作用的宏参数

当宏参数在宏定义中出现超过一次,这个参数就具有副作用,可能就会出现危险,导致不可预料的结果

来看下面的代码 (大坑)

#define MAX(a,b)	((a) > (b) ? (a) : (b))

int x = 5;
int y = 8;

int z = MAX(x++,y++);

z 是多少?
13 ? 15 ?
x,y 是多少?
 6,9?
 
这样写有坑啊 大坑
宏展开

((x++) > (y++) ? (x++) : (y++))
((5++) > (8++) ? (5++) : (8++))


这个问号表达式由前部分和后部分组成的 
前半部分都执行 而 后半部分 只执行问号确的那个

所以前面变为 6 > 9 ?
后面 执行 y++ 
那么 z = 9
y 是 10
x 是 6

卧槽 这样的代码写出来 搞毛啊

所以为了避免这样的问题出现,我们要把宏参数存储到临时变量中


int x = 5;
int y = 8;

x++;
y++;

int z = MAX(x,y);

这样就可以了
  

命名约定
value = max(a,b);
这是一个宏还是一个参数 ?

这样看根本区分不出来
为了不查看定义部分 直观一点

命名约定 宏 要大写字母

宏和函数的不同之处
属性#define 宏函数
代码长度每次使用时,宏代码都会插入到程序中,所以宏的定义要非常剪短的才有优势函数的代码只会出现在一个地方,每次使用时都会调用同一份代码
执行速度更快多于宏的 函数调用和返回时的额外的开销
操作符优先级宏是根据周围表达式的优先级,一定要加括号否则会出现上文中的问题中规中矩,结果比较好预测
参数类型宏与类型无关,只要参数的操作是合法的就可以除非使用模板,否则必须要指定参数的类型
ok 如果本文对您有帮助,请点个关注和赞支持一下小弟,谢谢了!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值