解释C预处理器代码

时间:2014-07-18 15:22:42

标签: objective-c c-preprocessor stringification

给定#define LOG_OBJECT(object) (NSLog(@"" #object @" %@ %@:%d”, [object description], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__));语句LOG_OBJECT(self);将产生:

  

2014-07-18 17:43:30.041 FrogCamera [12484:2144843]自我    ViewController.m:20

我希望了解预处理器代码的工作原理。如何查看预处理器生成的语句?

具体做法是:

  1. 为什么整个#define语句都包含在( )
  2. #object是否为提供的价值提供了文字替换?
  3. 为什么在@""之前要求#object
  4. @“” #object @“ %@ %@:%d”如何转换为@"self %@ %@:%d"
  5. 这是一个用法示例:

    @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
    

    请参阅GlobalUtilities.h了解LOG_OBJECT语句的来源。

2 个答案:

答案 0 :(得分: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 stringification 运算符。它将参数包装在引号中 - 例如,参数value转换为"value"
  3. 字符串化运算符创建一个C字符串,它是一个字符数组(char *)。作者需要一个NSString *,这就是他在开头添加@的原因。请注意,@"aaa" "bbb"相当于@"aaabbb"(此功能使我们能够将字符串拆分为多行)。但是,这不是很优雅。使用%s可以使它更简单。
  4. 仅转换为@"" "self" @" %@ %@:%d"。编译器将连续字符串视为一个字符串。

答案 1 :(得分:1)

如果要查看预处理器宏扩展到的内容,请打开文件,单击产品菜单,然后单击执行操作 - >预处理“ViewController.m” 。这将让您看到更换了宏的扩展源的外观。有关使用宏执行的操作的详细信息,请参阅Apple Docs