美文网首页
“#”的迷雾

“#”的迷雾

作者: 凯旋之歌 | 来源:发表于2017-04-10 16:38 被阅读0次

在代码中使用Autolayout时,大家都会使用NSDictionaryOfVariableBindings这个宏,这个宏可以生成一个变量名到变量值映射的Dictionary。比如NSDictionaryOfVariableBindings(button1, button2)将会生成一个{ @"button1" = button1, @"button2 = button2 }的Dictionary。它是怎么做到的呢?我们来看看这个宏的定义:

#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)

这个宏定义中有3个参数,后两个参数不难理解,但第一个参数中间有个#符号,语法上看起来比较怪异,这个是什么呢?以前在做越狱的mobilesubstrate开发时,其中定义的一堆宏频繁使用了这个符号,下面就来揭开#这个符号在宏定义中的迷雾。

预编译的一些知识

我们的代码在build时并不是直接进行编译的,在编译之前还进行了预编译处理。预编译会把include或import的文件导入到文件中,同时会将代码中用到的宏进行替换。注意宏是直接在代码中替换成宏的定义的,如果有嵌套也会逐层替换。

“#”指示一些预编译命令

预编译命令一般都是以#开头的,比如#include、#import、#if等,在这里就不一一说明了,本文主要说明一下#在宏定义里面的一些作用。

宏参数字符串化

在一个参数前加一个#,预处理时将会变成这个参数名的字符串常量,即字符串化(stringify)。比如:

#define GET_NAME(X) #X

int a = 0;

NSLog(@"%s",GET_NAME(a));      //output: "a"

NSLog(@"%s",GET_NAME(a+3));    //output: "a+3"

将会得到以下输出:

a

a+3

可以看出#,将参数原样转换成字符串常量,如果参数是一个表达式,那么输出这个表达式的原样字符串常量。

回头再看看NSDictionaryOfVariableBindings的定义:

#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)

如果这样生成两个button的映射:

NSDictionaryOfVariableBindings(button1, button2);

那么预编译时就会转换成:

_NSDictionaryOfVariableBindings(@"""button1, button2", button1, button2, nil);

由于两个常量字符串放在一起就是字符串常量串联,将变成两个字符串常量组合在一起的字符串常量,也就是上面是一个空字符串""和"button1, button2"串联,所以上面的代码等价于:

_NSDictionaryOfVariableBindings(@"button1, button2", button1, button2, nil);

那么_NSDictionaryOfVariableBindings函数就可以将它的第一个参数按逗号,分割开作为key,后面就是各个key对应的值了。因此这段代码就创建了一个内容为{ @"button1" = button1, @"button2 = button2 }的Dictionary。

命名的串联

#在宏定义中的另一个作用就是用于命名的串联,用##就可以串联它左右两边的命名,比如以下代码:

#define CONCAT(X, Y) X ## Y

NSString *helloworld = @"Hello, world!";

NSLog(@"%@",CONCAT(hello, world)); //output: "Hello, world"

CONCAT(hello, world)实际被转换成helloworld。注意一下,因为宏是预编译阶段进行展开的,就是说在编译之前,因此代码中的hello和world即使没有定义其实也是没问题的,预编译处理后,这两个命名是不存在的。

可选可变参数

##在宏定义中可以放在__VA_ARGS__之前表示可变参数可以为空,否则的话可变参数至少为一个了。

#define MYLOG(format, ...) NSLog(format, ##__VA_ARGS__)

MYLOG(@"Don't make an error!");

上面代码中MLOG中只有一个参数,如果不加##,则MLOG至少需要两个参数,在Xcode里将会出现编译错误。

相关文章

  • 迷雾迷雾在迷雾

    偶然间,亦或许是必然!我来到了你所在的城市。我在人海这端,你在人海那头。是奇妙的种种因素,我们相识于那个天气还算不...

  • 迷雾又见迷雾

    早上雨下的很认真,一瓢瓢的往下倒像要洗刷干净这人间的尘埃。世界是清净了吗,没有一个人联系我,讯息电话一个都...

  • “#”的迷雾

    在代码中使用Autolayout时,大家都会使用NSDictionaryOfVariableBindings这个宏...

  • 2018-05-14

    避开迷雾的最好方式就是冲进迷雾

  • 雾霾日记——迷雾迷雾在迷雾

    12月不知不觉已经过了一多半,在一个冬眠不觉晓,处处无啼鸟的早上,本人早早的醒来,推窗远眺(远眺得改为近观),一片...

  • 透过《迷雾》看清迷雾

    首先,这部剧给我了很大的震撼,改变了许多观念。同时,这也是我认真看完的第一部韩剧,之前看过《大长今》,但也只是停留...

  • 小肚玉帝

    妖先锋请教吞吐迷雾之法,原来林中迷雾是妖怪吐的扰乱心意的迷雾;悟空、沙僧经过真心诵经方得通过林中迷雾来到妖洞前,众...

  • 迷雾

    已然是早春的岳阳,天气开始阴晴不定,昨日个是艳阳的天气,今儿个就阴雨绵绵。 亲人,朋友都陆续去工作,好像生活又回到...

  • 《迷雾》

    一开始展现出来的是一起交通肇事案,而由于办案警察的怀疑和坚持,交织看职场的竞争及官场的贪腐,随看各方势力的...

  • 迷雾

    穿梭在森林当中,层层墨绿重叠,没有斑驳的阳光透过,也许是阴天吧……我一个人站在这片雪原,抬头望向幽深枝梢...

网友评论

      本文标题: “#”的迷雾

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