文档章节

“#”的迷雾

hejunbinlan
 hejunbinlan
发布于 2016/08/01 14:10
字数 866
阅读 6
收藏 0
点赞 0
评论 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。注意一下,因为宏是预编译阶段进行展开的,就是说在编译之前,因此代码中的helloworld即使没有定义其实也是没问题的,预编译处理后,这两个命名是不存在的。

可选可变参数

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

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

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

© 著作权归作者所有

共有 人打赏支持
hejunbinlan
粉丝 40
博文 532
码字总数 21018
作品 0
浦东
高级程序员
两位资深设计师谈设计和工具

随着国内软件行业整体水平的不断提升,原型设计作为产品设计中不可或缺的一部分,越来越多的得到了人们的重视。 Mockplus作为新兴的一款原型设计工具,凭借着更快更简单的原型设计方式和理念...

jongde ⋅ 2016/10/13 ⋅ 0

警惕!新版Net Transport(影音传送带)安装有猫腻

http://article.pcpop.com/show.aspx?topicid=1317935 由于早些时候FlashGet和NetAnts(网络蚂蚁)迟迟没有新版本发布,Net Transport(影音传送带)趁虚而入,以免费且支持流媒体下载迅速获...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

EasyTouch,KGFMapSystem插件的使用教程

1.Easy Touch使用教程 之前已经介绍过Unity自带的摇杆Joystick,它用起来很简单。但是它也存在很多局限,不能全部满足普通手游的一些需求,例如:要能方便地更好素材;能指定在某个区域显示,...

BoBoWang1991 ⋅ 2017/02/14 ⋅ 0

谈谈我对一些动漫句子的理解感悟〈一〉

你觉得被圈养的鸟儿为甚么无法自由翱翔天际?是因为鸟笼不是属于他的东西。 -------摘自《东京食尸鬼》 人类也就仿佛就是困在自己架构的鸟笼中日渐坚固的铁栅栏可是我们真正需要加固的确是我...

四十是似时 ⋅ 2017/07/05 ⋅ 0

平滑过渡的战争迷雾(一) 原理:Warcraft3地形拼接算法

本系列文章由七十一雾央编写,转载请注明出处。 http://blog.csdn.net/u011371356/article/details/9611887 作者:七十一雾央 新浪微博:http://weibo.com/1689160943/profile?rightmod=1&wv...

付翔 ⋅ 2015/03/27 ⋅ 0

前沿 | MIT自动驾驶技术突破:实现浓雾中物体观测和测距

     大数据文摘作品   编译:蒋宝尚   开发可见光自主车辆导航系统一直有一个主要障碍:无法应对雾蒙蒙的驾驶条件。   可见光系统比雷达探测系统表现更好,是因为其拥有高分辨率、...

大数据文摘 ⋅ 04/13 ⋅ 0

联众十年市场份额从85%跌至1% 4月公布新计划

身为中国游戏行业的元老级企业,联众世界2011年1月4日通过其官方博客发布通告,终于廓清传言已久的股权迷雾。 只是这一次的主角并非一度传言的盛大,亦非完美时空,北京伟德沃富投资顾问有限...

红薯 ⋅ 2011/01/09 ⋅ 4

阅读-1《天才在左,疯子在右》

《天才在左,疯子在右》原书 名《精神病人的世界》,刚开始以为要讲天才和疯子的故事,后来看到了原书名我明白了。 看到第二小节的时候才发现是以访谈录的形式记载的书。没有多余的话,只是人...

Reborn-D ⋅ 2016/03/30 ⋅ 0

quick-cocos2dx实现战争迷雾

因为在和策划讨论的时候发现游戏需要一个战争迷雾的效果,本来想到一般rts游戏的那种,但是手游不需要那么好的效果,之前我玩过一款《热战联盟》,然后还看到一个《文明变革2》的手游,出现了...

rangercyh ⋅ 2014/12/02 ⋅ 0

Sphinx(全文搜索)【资料整理】

Sphinx   “斯芬克司之谜使我们顺从自然。当迷雾逝去之后,我们会更加注意目前的需要。”——索福克尔斯   斯芬克司最初源于古埃及的神话,它被描述为长有翅膀的怪,通常为雄性,是“仁慈...

为梦而来 ⋅ 2014/04/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

笔试题之Java基础部分【简】【一】

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他 1.length、length()和size() length针对...

anlve ⋅ 27分钟前 ⋅ 2

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 51分钟前 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 56分钟前 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 快别开心了,你还没有女友呢。

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享吴彤的单曲《好春光》 《好春光》- 吴彤 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :小萝莉街上乱跑,误把我认错成...

小小编辑 ⋅ 今天 ⋅ 8

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部