Search code examples
objective-cc-preprocessorstringification

Interpreting C pre pre processor code


Given #define LOG_OBJECT(object) (NSLog(@"" #object @" %@ %@:%d”, [object description], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__)); The statement LOG_OBJECT(self); will produce:

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

I wish to understand how the preprocessor code works. How can I see the statement that the pre processor produced?

Specifically:

  1. Why the whole #define statement is wrapped in ( ) ?
  2. Is #object a text replacement for what ever value was provided ?
  3. Why the requirement for @"" before the #object ?
  4. Namely how is @“” #object @“ %@ %@:%d” is transformed to @"self %@ %@:%d" ?

Here’s a usage example:

@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

See GlobalUtilities.h for origin of LOG_OBJECT statement.


Solution

  • This is rather simple:

    1. Parenthesis in macros are used everytime when the expanded macro could do something unexpected. A typical example is:
      #define SUM(A, B) A + B
      SUM(1, 1) * 3 //the expected result is 6, the real result is 1 + 1 * 3 = 4 
      Adding parenthesis around every macro is a good programming convention to prevent this type of errors.
    2. #param is a stringification operator. It wraps the parameter in quotes - e.g., parameter value is converted to "value".
    3. The stringification operator creates a C string, which is an array of characters (char *). The author wanted a NSString *, that's why he is adding an @ in the beginning. Note that @"aaa" "bbb" is equivalent to @"aaabbb" (this feature enables us to split strings over multiple lines). However, this is not very elegant. Using a %s would make it a bit simpler.
    4. It is converted only to @"" "self" @" %@ %@:%d". The compiler considers consecutive strings as one string.