在代码中使用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。注意一下,因为宏是预编译阶段进行展开的,就是说在编译之前,因此代码中的helloworld即使没有定义其实也是没问题的,预编译处理后,这两个命名是不存在的。

可选可变参数

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

#define MYLOG(format, ...) NSLog(format, ##__VA_ARGS__)
MYLOG(@"Don't make an error!");

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

转自:http://blog.xcodev.com/blog/2013/12/16/mists-of-the-sharp/

转载于:https://www.cnblogs.com/yingkong1987/p/3463529.html

Xcode 中关于#的小知识相关推荐

  1. c语言冷门小知识,生活中的冷门小知识有哪些

    其实生活中充满了冷门知识,比如喝醋能够防止晕车.花生可以祛牙黄等等.下面是学习啦小编为大家整理的关于生活中的冷门小知识,希望大家喜欢! 生活中的冷门小知识 洗衣机强档比弱档节能 很多人没注意,在同样长 ...

  2. Python中的一些小知识

    1.时间处理 import time # time.struct_time结构体 time1 = time.localtime() print(time1) # 从1970年到现在的秒数 time2 ...

  3. ubuntu server中的一些小知识(个人收集贴)

    安装apache, ssh apt-get install apache2 a2enmod apt-get install openssh-server Bash的导航命令 大多数人都知道Bash的导 ...

  4. Javascript中的一些小知识收集

    1.在地址栏中传递参数时,对于包含特殊字符的处理: 使用encodeURIComponent()对参数值进行编码处理就可以了. 转载于:https://www.cnblogs.com/lfzwenzh ...

  5. vue 中indexof_前端小知识-Vue中使用indexOf() 方法

    定义和用法 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. 语法 stringObject.indexOf(searchvalue,fromindex) 参数描述searc ...

  6. CSS中的背景小知识

    1.css中的背景有很多属性,在写的时候可以用background:xxx  xxx 写在一起:也可以分开写,如background-color:background-image等等 2.背景颜色的写 ...

  7. Java匿名内部类中this的小知识(待补充完整)

    今日在看到Enumeration 借口的源码时发现,Enumeration 接口的asIterator 方法返回了一个迭代器,并使用匿名内部类(实现接口的匿名内部类).对迭代器中的方法进行了实现 de ...

  8. MSCKF中零碎的小知识

    当把MSCKF掰碎了一点一点细品时,发现这里面的东西确实很多,也很经典,滤波的多传感器融合绝对值得去细细研究. 1.关于ros的时间戳问题 roscpp 里有两种时间表示方法:时刻 (ros::Tim ...

  9. 在日常办公中如何正确使用计算机,日常办公中的节能降耗小知识

    节能降耗,从我做起,从点滴做起,从举手之劳做起,今天就让我们来分享下日常办公中节能的小知识吧~ 推广使用节能灯 使用电子镇流器代替电感式镇流器.以节能灯(T5T8)代替白炽灯,可节省高达70%至80% ...

最新文章

  1. 甲骨文推出低成本高速公共与混合云方案,矛头直指AWS
  2. python--内置函数
  3. 用python控制钉钉软件_Python—实现钉钉后台开发
  4. json 字符串反序列化成DataSet
  5. Python跨文件引用模块
  6. 树莓派4b自带wifi_树莓派4B日志二:WiFi远程配置与换源
  7. C++socket编程(七):7.3 http的响应协议
  8. 手把手带你深入解析静态分派 动态分派原理 | 原力计划
  9. 虚拟机中试用windows 8(视频)
  10. mac删除的文件还能找回吗
  11. 终极.NET混淆器丨.NET Reactor产品介绍
  12. 小程序源码:全新独立后台修复登录在线答题
  13. C#实现改变图片的像素
  14. 阿里云计算工程师ACP考题归类解析
  15. 2021.11.08【web刷题记录】
  16. win7忘记密码怎么办,Administrator忘记密码解决办法【完美、简单、有效】
  17. Androidstudio报错问题之R飘红
  18. JS实现点击导航栏鼠标左右滑动 (适用于PC端和移动端)
  19. 【转】腾讯 百度 网易游戏 华为Offer及笔经面经
  20. 一文带你了解优秀的Go 语言开源项目

热门文章

  1. 「MTA」的「錯誤訊息代碼」
  2. linux部署MantisBT(三)部署MantisBT
  3. Android应用博客目录
  4. 学生、课程、分数的设计(重要)
  5. delphi之http通讯
  6. DirectShow Filter 基础与简单的示例程序
  7. nginx相关的一些记录
  8. apple个人开发者证书无线发布app的实现(转)
  9. Sencha Touch 2.3 自定义主题皮肤,颜色
  10. C#开发中关于加密解密字符串的使用方法