Obj-C is essentially a preprocessor on top of a C compiler. Whether that C compiler is C89, C99, or C++11 is up to you.
Obj-C also includes the Foundation classes that were originally introduced with the OpenStep SDK in 1994 (NSObject, NSString, NSNumber, NSArray, NSRunLoop, NSAutoreleasePool, etc.).
Is it possible to see this straight C translation? Using Clang for example. I'm sort of aware of the "objc_msgSend" business, but would like to see more.
Talking of OpenStep, after seeing some of those NeXT videos on HN the other day, I found a torrent of OpenStep 4.2 incl the dev tools. It's a VMware image and boots and runs just fine. Pretty nifty. Then I noticed OpenStep 5.0 redirects to Mac OS X on Wikipedia!
id foo = ((id)(id, SEL)objc_msgSend)(self, @selector(bar)); [2, 3, 4]
1. Because we're calling the IMP, or implementation, directly, we don't need a cast (like we do below, with objc_msgSend).
2. Casting the function is optional, but, helps to prevent things like endian differences and your return value getting mangled when using the same code on PPC and Intel. Not too big of a deal anymore.
3. There are actually two other varieties of objc_msgSend, depending on your return type — specifically, floating point calls should use objc_msgSend_fpret and calls that return a struct should use objc_msgSend_stret.
4. I hope I got this cast right, I didn't try to compile it.
(The first example is saying to self to call the selector (method) named 'bar'. The second example is telling self to call the method 'performSelector:' with an argument of 'bar'.)
The runtime may or may not be smart enough to optimize this out. It has never been a bottleneck for me to bother looking into it, and I haven't come across anything to indicate one way or the other.
Check out clang's -rewrite-objc option. It outputs C++, not C, and isn't entirely truthful since Obective-C is compiled directly these days, but should give you what you're after.