[转载ios 宏]

define PLAYSOUNDEFFECT(...) [[GameManager sharedGameManager] playSoundEffect:@#VA_ARGS]

这样的代码你能看懂吗?
看懂了你就是高手了 哈哈
(转载 http://blog.csdn.net/songrotek/article/details/8929963)
1 关于宏的定义
A macro
is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like
macros resemble data objects when used, function-like
macros resemble function calls.
有两种宏的类型,一种是类对象的宏,封装使用的数据对象,另一种是类函数的宏,封装函数的调用。在ObjC里面,那就是可以封装Method的使用,如文章一开始的代码
1.1 类对象的宏
最基本的使用:

define BUFFER_SIZE 1024

foo = (char *) malloc (BUFFER_SIZE);

foo = (char *) malloc (1024);

就是最基本的替换。

通常宏的名称都是用大写字母。


define NUMBERS 1, \

            2, \  
            3  

int x[] = { NUMBERS };
==> int x[] = { 1, 2, 3 };

在宏定义中,如果要换行,使用“"符号。然后经预处理后还是在同一行。


C预处理器是按顺序读取程序,因此宏定义生效在宏定义之后。
foo = X;

define X 4

bar = X;
ces

foo = X;
bar = 4;


宏调用时,预处理器在替换宏的内容时,会继续检测内容本身是否也是宏定义,如果是,会继续替换内容。

define TABLESIZE BUFSIZE

define BUFSIZE 1024

TABLESIZE
==> BUFSIZE
==> 1024


宏定义以最后生效的定义为准,因此下面的代码TABLESIZE对应37

define BUFSIZE 1020

define TABLESIZE BUFSIZE

undef BUFSIZE

define BUFSIZE 37


如果宏定义内容包含了名称,则预处理器会终止展开防止无限嵌套(infinite resursion)
1.2 类函数宏

define lang_init() c_init()

lang_init()
==> c_init()

类函数宏的名称后面加了"()"。

define lang_init () c_init()

lang_init()
==> () c_init()()

并且"()"必须紧随在名称后面否则就会认为是类对象宏。

1.3 宏参数
在类函数宏里面可以添加参数使得更像真正的函数
  #define min(X, Y) ((X) < (Y) ? (X) : (Y))
   x = min(a, b); ==> x = ((a) < (b) ? (a) : (b));
   y = min(1, 2); ==> y = ((1) < (2) ? (1) : (2));
   z = min(a + 28, p); ==> z = ((a + 28) < (p) ? (a + 28) : (*p));

基本的使用和函数的定义类似,当然宏里面都是实际参数,用逗号隔开。预处理时,先是将宏展开,然后将参数放进宏的主体中,再检查一遍完整的内容。


如何宏里面有字符串的内容,即使与参数名相同,也不会被替换。如下:
   foo(bar) ==> bar, "x"

1.4 字符串化

使用”#“预处理操作符来实现将宏中的参数转化为字符串。例子如下:
  #define WARN_IF(EXP) \
  do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
  while (0)
  WARN_IF (x == 0);
   ==> do { if (x == 0)
fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);

这个字符串化会将参数中的所有字符都实现字符串化,包括引号。如果参数中间有很多空格,字符串化之后将会只用一个空格代替。

然后没有什么方法可以直接将参数转化成单一的字符char

define xstr(s) str(s)

define str(s) #s

define foo 4

str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4"

出现上面的结果是因为在使用str(s)时,s是字符串化,所以宏没有扩展开。而使用xstr(s)时s作为一个参数,因此先把宏完全扩展然后再放进参数。

1.5 连接
使用"##"操作符可以实现宏中token的连接。
struct command
{
char name;
void (
function) (void);
};

struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};

define COMMAND(NAME) { #NAME, NAME ## _command }

struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};

如上,使参数NAME对应的字符与_command连接起来,而不进行其他转化。当然要注意连接后的字符必须是有意义的,否则只会出现错误或警告。然后C预处理器会将注释转化成空格,因此在宏中间,参数中间加入注释都是可以的。但不能将"##"放在宏的最后,否则会出现错误。1.6 多参数宏(Variadic Macros)

define eprintf(...) fprintf (stderr, VA_ARGS)

eprintf ("%s:%d: ", input_file, lineno)
==> fprintf (stderr, "%s:%d: ", input_file, lineno)

使用标识符_VA_ARGS来表示多个参数,在宏的名称中则使用(...)在C++中也可以使用如下的方式:

define eprintf(args...) fprintf (stderr, args)

结果是一样的。------------------------------------------------------------------------------------------------"##"的特殊用法:
  #define eprintf(format, ...) fprintf (stderr, format, ##VA_ARGS)
  eprintf ("success!\n")
   ==> fprintf(stderr, "success!\n");

将"##"放在","和参数之间,那么如果参数留空的话,那么"##"前面的","就会删掉,从而防止编译错误。1.7 取消或重新宏定义这个看下面的代码就明白:
   #define FOO 4
x = FOO;
==> x = 4;
#undef FOO
x = FOO; ==> x = FOO;
  These definitions are effectively the same:
#define FOUR (2 + 2)
#define FOUR (2 + 2)
#define FOUR (2 /* two */ + 2)
  but these are not:
#define FOUR (2 + 2)
#define FOUR ( 2+2 )
#define FOUR (2 * 2)
#define FOUR(score,and,seven,years,ago) (2 + 2)

对于重定义,如果定义的宏不一样,那么编译器会给出警告并使用最新定义的宏。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • http://www.open-open.com/lib/view/open1390651437117.html ...
    Xtuphe阅读 1,244评论 0 10
  • 一直以来用宏定义#define也就是定义一些简单的常量,至多也就是定义一个函数,很少关注宏定义的用法。直到看到这样...
    ant_flex阅读 1,941评论 0 3
  • 宏定义在C系开发中可以说占有举足轻重的作用。底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可...
    你好自己阅读 1,050评论 0 5
  • C中的预编译宏定义 2009-02-10 作者: infobillows 来源:网络 在将一个C源程序转换为可执行...
    白水灬煮一切阅读 1,578评论 0 5
  • 实验班开课两周之后,我和孩子们的交流也越来越多了。无论是从学习风格测试的结果来看,还是从我对他们的主观感知来...
    shinezs阅读 149评论 0 0