Alex Gray
Alex Gray

Reputation: 16463

How to pass the result of a function as a Macro variable?

Say I've set up a macro expansion as follows...

#define WARN_START @"DANGER"
#define WARN_RESET @"THE COAST IS CLEAR"
#define WARN(x) WARN_START x WARN_RESET

INPUT WARN(@"*** Your boss is coming. ***")

OUTPUTDANGER *** Your boss is coming. *** THE COAST IS CLEAR

and lets suppose I have a function…

NSString * WhosComing(void){ return @"*** Some fool. ***"; }

How can I pass the result of such a function to the macro, without first assigning it to a variable, i.e.

WARN(WhosComing())

ERRORexpected ')'

I've messed around with extra parenthesis, i.e.

#define WARN((x))…. or ...WARN_START (x) WARN_RESET but…

ERRORinvalid operands to binary expression, etc.

as well as trying to pass the cuntion as a pointer, or something, i.e. WARN(&WhosComing()), to no avail. I'm sure this is possible / straightforward… but I don't have a CS degree, so I never learned how.. Easy answer for someone?

Upvotes: 0

Views: 140

Answers (2)

Chuck
Chuck

Reputation: 237010

Well, you can't have the result of the function inserted at compile-time, as obviously the function's result doesn't exist until it is executed. But you can do something like this:

#define WARN(x) [NSString stringWithFormat:@"%@ %@ %@", WARN_START, (x), WARN_RESET]

But that's no better than a function, is it? If the argument to the macro were a literal string, you could write it the way you want. But since the argument's value is not even known at compile time, there's not a whole lot you can do with it at the macro-expansion stage, so emitting an expression that will produce the value you want at run time is pretty much your only option.

Upvotes: 2

CRD
CRD

Reputation: 53000

You cannot do what you are attempting with a macro. It is a feature of the C language (and hence Objective-C, C++) that adjacent string literals are concatenated during compilation and this is extended for Objective-C to included NSString literals.

Your macro expands to:

@"DANGER" @"*** Your boss is coming. ***" @"THE COAST IS CLEAR"

and the compiler then concatenates these 3 literals into 1.

However pass in your function and you get:

@"DANGER" WhosComing() @"THE COAST IS CLEAR"

which is invalid code.

There are various solutions; you could use a real function, inlining it if are really concerned over the cost of the function call:

NS_INLINE NSString *WARN(NSString *msg)
{
   return [NSString stringWithFormat:@"%@%@%@", WARN_START, msg, WARN_RESET];
}

Upvotes: 3

Related Questions