2014-07-18 86 views
1

鉴于#define LOG_OBJECT(object) (NSLog(@"" #object @" %@ %@:%d”, [object description], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__));声明LOG_OBJECT(self);将产生:解读下预预处理器代码

2014年7月18日17:43:30.041 FrogCamera [12484:2144843]自 ViewController.m:20

我想了解预处理器代码的工作原理。我怎样才能看到预处理器产生的声明?

具体做法是:

  1. 为什么整个#define语句被包裹在()
  2. #object是否提供了一个文字替换提供了什么价值?
  3. 为什么要求@""之前#object
  4. 即是如何将@“” #object @“ %@ %@:%d”转换为@"self %@ %@:%d"

下面是一个使用示例:

@interface ViewController() 
#define LOG_OBJECT(object) (NSLog(@"" #object @" %@ %@:%d", [object description], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__)); 
@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    LOG_OBJECT(self); 
    // = 2014-07-18 17:48:19.439 FrogCamera[12597:2151087] self <ViewController: 0x79755000> ViewController.m:20 
    (NSLog(@"self %@ %@:%d", [self description], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__)); 
    // = 2014-07-18 17:48:19.440 FrogCamera[12597:2151087] self <ViewController: 0x79755000> ViewController.m:21 
} 
@end 

为LOG_OBJECT声明的起源见GlobalUtilities.h

+0

基于C,2.'#'是一个运算符。 4.相邻的字符串文字是连接的。 – chris

回答

3

这是相当简单:

  1. 括号中宏每次使用时扩展的宏可以做一些意想不到的。一个典型的例子是:
    #define SUM(A, B) A + B 
    SUM(1, 1) * 3 //the expected result is 6, the real result is 1 + 1 * 3 = 4
    围绕每个宏添加括号是防止此类错误的良好编程约定。
  2. #param stringifying运算符。它将参数包含在引号中 - 例如,参数value转换为"value"
  3. 字符串化操作符创建一个C字符串,它是一个字符数组(char *)。作者想要一个NSString *,这就是为什么他在一开始就加入@。请注意,@"aaa" "bbb"等同于@"aaabbb"(此功能使我们能够将字符串拆分为多行)。但是,这不是很优雅。使用%s会使它更简单一些。
  4. 它只转换为@"" "self" @" %@ %@:%d"。编译器将连续字符串视为一个字符串。
1

如果你想看到什么预处理宏扩展到,打开文件后点击产品菜单,然后执行动作 - >预处理“ViewController.m”。这可以让你看到扩展的源代码,宏代替的样子。有关可以用宏做什么的详细信息,请参阅Apple Docs

+0

行动 - >预处理是一个美妙的提示。谢谢。 –