为了账号安全,请及时绑定邮箱和手机立即绑定

【学习打卡】第3天 宏函数、条件编译

标签:
C

课程名称:C语言系统化精讲 重塑编程思想 打造坚实的开发基础

课程章节:第五章 预处理和宏

授课老师:bennyhuo

课程内容

C宏函数

C语言中 除了简单的利用 宏代替常量以外,我们也可以利用宏编写简单的宏函数。
之所以能称之为函数,是因为其可以带入参数。
简单的例子:

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

int max = MAX(1, 3)

但注意,这样的定义,在嵌套时,可能会出现错误,来源于替换后各种表达式的优先级不同。所以,在实际情况中,我们一般会添加一对括号,保证参数在进行运算时始终保持表达式的独立计算。
实际情况:

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

另一个特例,如果在表达式中有自增运算,在替代后,会不经意间多计算一次:

max = MAX(max++, 5)
->
max = (max++) > 5 ? (max++) :5 // 多执行了一次

总之,在写完宏后,使用宏函数的过程要保证使用 没有副作用 的表达式。

ps:副作用是语言中的一个概念,即表达式和函数不改变变量或者状态,只返回某个值。

多行宏使用 \ 连接:

#define IS_HEX_CHARACTER(ch) \
((ch) >= '0'  && (ch) <= '9' ) || \
((ch) >= 'A' && (ch) <= 'F' )|| \ 
((ch) >= 'a' && (ch) <= 'f )  

宏展开,\并不会替换,换行符只是给编译器看的。而宏函数又因为自身没有类型的要求,所以其 可在C 中被用来方便的进行多类型的通用函数。
图片描述

条件编译

在头文件中,我们常见可以见到如下宏定义:

#ifdef XXXXX_H
#define XXXXX_H

//statement
#endif

那么既然引入头文件就可以将一些函数引入,为什么要加入这些判断呢?
答案就是 :防止引入同一个头文件多次 ,因为引入同一段函数多次,在编译上一般会报错。

在多个头文件文件互相引入的时候,这可以有效避免多次引入同一段函数。

而条件编译的语句含义也非常明显:

1. #ifdef : 如果定义了
2. #ifndef : 如果没定义
3. #if 如果...

最后,他们都要和 #endif 搭配

而 

有一个通用的小技巧,便是使用 defined () 这个函数可以判断宏是否定义,通常搭配 #if 实现和ifdef 同样的作用。最终达到在不同宏,实现不同功能的作用,如:

void dump(char *message){
#ifdef DEBUG 
	puts(message);
#endif
}

当然你可以定义 #define DEBUG 做到调试开关的作用,更方便的做法是:
在编译时,只要了加上了宏 gcc -D DEBUG 即可

CMAKE中,如下加入定义:

	target_compile_definition(${name} PUBLIC DEBUG)

有一个有意思的东西,可以判断在 C or C++ 的环境:

#ifdef __cplusplus
extern "C"{
#endif

//....

#ifdef __cplusplus
};
#endif

当然,宏编译对于跨平台编译也非常好用:
图片描述

课程收获

  • 理解了为什么要有条件编译
  • 条件编译对 DEBUG 类的编译的作用
  • 稍微熟悉了 CMAKE 中 添加编译选项的方法
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消