部分内容转自:
http://blog.csdn.net/dotphoenix/article/details/4345174
看到之前大神的代码,很多地方都没看懂,还是感觉很厉害的样子,所以开始一点一点的看。先从基本的入手吧,看到一些宏定义就差了一下。
自定义的解析XML的类,有一些对@property的定义:
@property (nonatomic, property_attribute) property_type property_name; \
- (NSString*)class_name_of_##property_name;
#define TM_SERIALIZABLE_SYNTHESIZE(property_type, property_name) \
@synthesize property_name = _##property_name; \
- (NSString*)class_name_of_##property_name \
{ \
typeof(_##property_name) temp;\
temp = (property_type) _##property_name;\
return @#property_type; \
}
##被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定 是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用:
struct command { char * name; void (*function) (void); }; #define COMMAND(NAME) { NAME, NAME ## _command } // 然后你就用一些预先定义好的命令来方便的初始化一个command结构的数组了: struct command commands[] = { COMMAND(quit), COMMAND(help), ... }
就是连接参数和参数或者是参数和其他字符的功能。
顺便说下
#的作用:
在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号。比如下面代码中的宏:
#define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP "/n"); } while(0)
那么实际使用中会出现下面所示的替换过程:
WARN_IF (divider == 0); 被替换为 do { if (divider == 0) fprintf(stderr, "Warning" "divider == 0" "/n"); } while(0);
这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。
其他的还有:
关于...的使用
错误的嵌套-Misnesting
由操作符优先级引起的问题-Operator Precedence Problem
消除多余的分号-Semicolon Swallowing
Duplication of Side Effects