美文网首页
对宏的简单认识和使用

对宏的简单认识和使用

作者: 永远保持一颗进取心 | 来源:发表于2017-07-10 09:26 被阅读9次

参考文章:https://onevcat.com/2014/01/black-magic-in-macro/
http://www.cnblogs.com/alexshi/archive/2012/03/09/2388453.html
https://zhidao.baidu.com/question/425382312987430932.html

宏分为两类

  • 对象宏(object-like macro)

  • 函数宏(function-like macro)

对象宏

对象宏相对比较简单,一般是用来定义一些常数:

#define M_PI 3.14159265358979323846264338

编译时,编译器会在语义分析认定是宏,会将 M_PI 替换为具体的圆周率数字,这个过程称为宏的展开。

函数宏

函数宏,意味着它的行为类似于函数;它可以接受参数。只要在宏名称(上面例子中的 M_PI 就是宏名称)的后面加上括号,就成为函数宏。

#define MIN(A, B) (A < B ? A : B)

这是一个比较两个数大小的宏,A和B 是宏可以接受的两个参数,宏展开时,它们会分别代入宏体中的 A和B。宏体用括号括起来是要防止宏展开时不如预期,例如

我要输出两个数字中较小数字的10倍:

#define MIN(A, B) A < B ? A : B
int a = 100;
int b = 200;
NSLog(@"smaller: %d", 10*MIN(a, b));

输出则为 200,跟预期的1000不一样。因为宏展开后是这样的

10 * a < b ? a : b

先做了乘法,再进行比较。所以不管是对象宏还是函数宏,这点都要注意。

关于#和##、__VA_ARGS__

# 运算符可以将宏的参数转化为字符串字面量,它仅仅出现在函数宏中。
使用方法

#define LOG(A, B) NSLog(@""#A" = %d, "#B" = %d" , A, B)
 
int main(int argc, char *argv[]) {
    @autoreleasepool {
        int a = 100;
        int b = 200;
        LOG(a, b);
    }
}

输出为: a = 100, b = 200

## 运算符可以将两个标识符粘合在一起。如

#define GLUE(A, B) A##B
 
int main(int argc, char *argv[]) {
    @autoreleasepool {
        int a = 100;
        int b = 200;
        int ab = 300;
        NSLog(@"%d", GLUE(a, b));
    }
}

输出:300

__VA_ARGS__

在一些宏参数中会出现 ‘...’,‘...’ 指的是可变参数,意思是可以接受零个或者是多个参数。而在宏体里,对应的便是 __VA_ARGS__ ,例

#define WHLOG(fmt, ...) NSLog(fmt,__VA_ARGS__)
int main(int argc, char *argv[]) {
    @autoreleasepool {
        int a = 100;
        WHLOG(@"Hello world %d", a);
    }
}

输出为:Hello world 100

但是这里有个问题:当对 ‘...’ 输入零个参数的时候,当展开宏的时候会多了一个逗号出来,这时候编译会不通过。针对这个问题,可以用 ##__VA_ARGS__ 这个代替 __VA_ARGS__ ;当输入零个参数的时候,预处理器会把多出它之前多出的那个逗号去掉。

相关文章

  • 对宏的简单认识和使用

    参考文章:https://onevcat.com/2014/01/black-magic-in-macro/htt...

  • 宏、参数宏、宏嵌套

    简单宏容易理解,如: 带参数的宏以及宏嵌套: 使用BOOTCMD时就像函数一样使用,方便。如上语句BOOTCMD(...

  • ios宏的总结

    宏定义为对象宏和函数宏,对象宏通常是对一些简单的对象进行替换,如#define M_PI 3.1415,函数宏(在...

  • 009 Rust 异步编程,select 宏中的使用 defau

    说明 在前一节,我们简单介绍了select宏。其实在select宏中,还可使用default和complete,前...

  • #define、#undef、Preprocessor Macr

    #define 简单的宏定义。 没有设置值的宏定义不能在if条件语句和#if预编译语句中使用,但是可以在#ifde...

  • dubbo源码(三)-Adaptive使用

    前言 前面两篇文章对dubbo SPI的使用和原理进行简单的讲解,大家应该对dubbo SPI有了认识。在 Dub...

  • 力宏 ❤唯一

    今天去看了力宏的电影“火力全开” ,说实话,感动和震撼之余,我对力宏有了更深的认识,我和他更近了。 我喜欢...

  • 精进

    1、认识问题 正确地认识问题,而不是简单地使用别人的问题表述,可以基于对现实处境的深入和缜密的观察。 2、独立思考...

  • 使用全局函数自定义NSLog ,用于SDK

    普通项目中 因为可以直接使用宏,简单做如下定义即可使用

  • OC 链式编程 简单介绍

    1、设置属性和输出属性 定义相关宏 定义几个简单的方法,其中包括有返回值和没有返回值 以上就是简单的使用介绍 i...

网友评论

      本文标题:对宏的简单认识和使用

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