【Just For Fun】
本系列纯粹娱乐、研究用。一些旁门左道的东西。
事实上可能完全没用。 (๑•̀ω•́๑)
说一点基础的宏知识,#
和 ##
,
曾经有在 另一些地方 写过,又搬过来一下。
▌预处理器:
预处理器,于编译前进行。
例如常用的 #include
和 #define
,#define
即 宏/巨集 (marco) 。
以 #
开头都是预处理器,其他的例子如
例如: #if
, #endif
, #else
, #elif
,#ifdef
, #ifndef
, #error
, #pragma
, #typedef
等等。
详情可参考 microsoft 的 C/C++ 前置处理器参考
以及 Preprocessor Directives | Microsoft Docs
▌宏 #define:
宏和指标可谓是 C 语言的精髓,
依靠它们可以创造无限可能,极为博大精深。
宏可以节省工作量,同时增加可读性,使代码变得优雅。
即使宏的本身不优雅、可读。
一般代换展开这种基础知识就不说了,以下讲述 #
和 ##
前置处理器运算子的功能,
详情亦可参考 microsoft 的 前置处理器运算子
▌#
:
#
— 字串化运算子,
放在宏参数前,展开时中参数两端加入 "
,使其字串化。
例子:
#define str(x) #x
使用 str( 9qwe7 h5d1v3jk6w )
会被展开为
" 9qwe7 h5d1v3jk6w "
___
另外,根据定义,
如果在字串常值中使用引数包含通常需要逸出序列时 (例如引号 (") 或反斜线 () 字元),必要的逸出反斜线字元就会自动插入至该字元之前。
#
会自动添加逸出反斜线字元()
利用此特性可以简化大量需要逸出反斜线的字串。
___
例如 我要输入 the "" mean escaped character.
作为字串
正常:"the "" mean escaped character."
,
宏: str(the "" mean escaped character.)
。
某程度上来说,可读性会较好。
还有常见的档案路径,如果我要输入 D:UserDocumentsC_Test.txt
作为档案路径。
正常:"D:UserDocumentsC_Test.txt"
宏: str(D:UserDocumentsC_Test.txt)
。
可以不用考虑要不要加 ,也可以打少一些字元。
▌##
:
##
— 语汇基元带入的运算子,
这名字是 microsoft 改的,有时称为「合并」运算子。
可以合并文字,例子:
#define mix(x) abc##x
使用 mix(d)
会被展开为 abcd
意义何在呢?因为识别字(identifier)是以空格等等作为分隔,若果:
#define mix(x) abcx
预处理器无法辨认出 x
,它只看到有 abcx
这个识别字。
加入 ##
可以令它识别出 宏参数 并将其合并。
另外,##
前后的空格可有可无,
即 abc##x
等价 abc ## x
▌阻止另一个宏的展开:
一旦在使用了 #
或 ##
在 宏中,
其宏参数是另一个宏 ,
将会阻止另一个宏的展开。
例子:
#define foo abc
#define foo2(x) x##123
foo2(foo)
的结果并不会是 abc123
,
不会展开作为参数的宏 foo
,
所以结果是 foo123
。
可参看 C宏展开的几个注意事项 - nanoix9 - 博客园,貌似很详细。
注意一下 VS 的展开规则,跟其他编译器不一样
(来自作者血泪的教训。Q _____ Q)
▌预先定义的宏:
有一些预先定义在前置处理器中的宏:__LINE__
:从原始档开头起算, __LINE__
所在的行数__FILE__
:档案名称(字串常数)__DATE__
:以 Mmm dd yyyy 格式(eg. Oct 31 2018),表示编译时的日期__TIME__
:以 hh:mm:ss 格式,表示编译时的时间 (字串常数)__STDC__
:若 1 ,表示编译器遵循 ISO C 标准__STDC_VERSION__
:若支援 C99,数值为 199901L
, 若支援 C11,数值为 201112L
。__func__
:函式名称 (C99)
...还有很多,不全部列出。
__LINE__
和 __FILE__
常用于错误讯息。__func__
也是,不过是 C99 才支援。
还有一些是编译器扩展,但C标准好像没有支持的。
像是 __COUNT__
,
这个很实用,未来可能会讲解一下。
___
最后特意推荐 宏定义的黑魔法 - 宏菜鸟起飞手册,
循序渐进,很好,很详细,很深入。
学到不少新技术,
推荐推荐~!
▌参考资料:
预处理器 - 维基百科,自由的百科全书
C/C++ 前置处理器参考 C/C++ Preprocessor Reference
前置处理器运算子 Preprocessor Operators
C宏展开的几个注意事项 - nanoix9 - 博客园
[C 語言] 程式設計教學:如何使用巨集 (macro) 或前置處理器 (Preprocessor)
宏定义的黑魔法 - 宏菜鸟起飞手册
___
原文網址(作者是我):2019 iT 邦幫忙鐵人賽:Day 21:重溫前置處理器、巨集( #, ## )、預先定義的巨集
___
【Just For Fun】俺 是 目 录 !
___
下一篇:【Just For Fun】C - 可变参数函数、可变参数宏 __VA_ARGS__、额外的逗号