Writing @ prefixed macros

While writing my own debugging lib, an idea I was toying with was having a debug macro look like one of the built-in @ compiler directives, e.g. @selector, @encode, etc.

Since macro names must be identifiers, and identifiers can’t have @s in them. You can’t do this:

#define @debug(fmt, ...) \
  NSLog(fmt, ##__VA_ARGS__)

The trick, we’ll write our macro such that the macro definition will be missing an @ prefix. When the definition expands, the @ before the real identifier will make our code valid.

#define debug(fmt, ...) \
  try {} @finally {} \
  NSLog(fmt, ##__VA_ARGS__)

Here, the try in the macro is missing its @ prefix. So before and after the preprocessor does its job, we have:

// before
@debug(@"My name is Travis.")

// after
@try {} @finally {}
NSLog(@"My name is Travis.");

Neat. It’s possible you could clash with directives that are added in the future, so namespacing your macros is probably best (e.g. TRVSDebug), especially in shared libraries. However, I have seen this techniqued used in libextobjc — providing macros such as @weakify and @strongify.

Follow me on Twitter to keep up with what I’ve learned building my personal finance tool, Stash.

Subscribe to my mailing list to learn more about technology and business.

Your email will never be shared with anyone else.

Read more posts …
Written: January 10th, 2014
Categories: objc, c, macros