I'm sure I'll get 20 people saying "why would you want to do that anyways"... but, I'm going to ask my question none-the-less because it's somewhat academic in nature.
I'd like to use C macros to redefine [ClassName new]
into something like: new(ClassName)
, and I'm wondering how to do this. I'm not super comfortable with C macros to begin with (I know - embarrassing - I should be) - and I'm definitely not comfortable mixing them in with my Objective-C code. So, on with the question...
First, being it's a preprocessor thing, can I do a simple substitution like such:
#define new(x) [x new]
or, for whatever reason, do I need to drop down to the objective-c runtime, and do something more akin to:
#define new(x) objc_msgSend(class_createInstance(x, 0), sel_registerName("init"))
What are the downfalls of doing something like this?
Is this kind of thing used often by others, or, would someone look at it and say "what the heck are you doing there"? (and should I care)
Thanks
EDIT:
It occurred to me after posting this, that I have, in fact, see this kind of thing before - in the Three20 lib, where they do things like this:
#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }
#define TT_INVALIDATE_TIMER(__TIMER) { [__TIMER invalidate]; __TIMER = nil; }
// Release a CoreFoundation object safely.
#define TT_RELEASE_CF_SAFELY(__REF) { if (nil != (__REF)) { CFRelease(__REF); __REF = nil; } }
So probably my question becomes simply; What are the downfalls of doing this, and is it a relatively accepted practice, or something that's going to get me into more trouble than it's worth?
Macros can be used in many languages, it's not a specialty of objective-c language. Macros are preprocessor definitions. What this means is that before your code is compiled, the preprocessor scans your code and, amongst other things, substitutes the definition of your macro wherever it sees the name of your macro.
"Macros" in C are a simple string substitution (including substitution of arguments) done by the C pre-processor (on Linux, that would be cpp foo. c ) before compilation is done. Run just the C pre-processor on your source to see exactly how the macro is expanded. It doesn't exactly act like a function.
The Concept of C MacrosMacros can even accept arguments and such macros are known as function-like macros. It can be useful if tokens are concatenated into code to simplify some complex declarations. Macros provide text replacement functionality at pre-processing time. The above macro (MAX_SIZE) has a value of 10.
Macros are processed first, and they are operating on the plain text source code. So yes, you can have your new
macro generate Objective-C syntax or plain C syntax or even invalid syntax if you like.
The downfalls of using a macro in general is that, because it is parsed and processed in a separate step, it's possible to write macros that don't behave how you expect even when everything looks fine.
For example, this macro:
#define MAX(x,y) x > y ? x : y
Looks OK, but say you used it like this:
z = MAX(a,MAX(b,c));
It would be expanded by the preprocessor into something like this:
z = a > b > c ? b : c ? a : b > c ? b : c;
Which won't actually give you the max of the three arguments. To solve this you need to liberally sprinkle parenthesis in your macro definition, even where you don't think it is needed:
#define MAX(x,y) ((x) > (y) ? (x) : (y));
That fixes it, except I added a semicolon to the end, which is an understandable habit from writing a lot of C code, except now our macro expands to:
z = ((a) > (((b) > (c) ? (b) : (c));) ? (a) : (((b) > (c) ? (b) : (c));));;
Syntax errors!
If you look at how MAX
is actually defined in Objective-C, it's pretty mess, but that's what you have to do to write macros safely. And you also need to consider that:
z = MAX(expensiveComputation(), reallyExpensiveComputation())
Will, unlike a function, actually execute one of those functions twice, unless you use a trick in your macro to basically emulate parameter passing.
So, to answer your question, yes it is totally possible, but writing safe macros is really hard. And you're doing this so you can pretend your Objective-C code is actually code in another language... Why would you want to do that, anyways?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With