I'm trying to wrap my head around some of the differences in usage and syntax in C vs. Objective-C. In particular, I want to know how (and why) the usage differs for the dot operator and the arrow operator in C vs. Objective-C. Here is a simple example.
C Code:
// declare a pointer to a Fraction
struct Fraction *frac;
...
// reference an 'instance' variable
int n = (*frac).numerator; // these two expressions
int n = frac->numerator; // are equivalent
Objective-C Code:
// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];
...
// reference an instance variable
int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator??
So, seeing how frac
is the same in both programs (i.e. it is a pointer to a Fraction object or struct), why are they using different syntax when accessing properties? In particular, in C, the numerator
property is accessed with frac->numerator
, but with Objective-C, it is accessed using the dot operator, with frac.numerator
. Since frac
is a pointer in both programs, why are these expressions different? Can anyone help clarify this for me?
frac
is actually not the same in both programs.
A C Fraction
is a struct
, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C
is with the dot (.
) operator. Objective-C maintains this operator when you use struct
s. For convenience, you can perform a dereference-and-dot operation using the arrow (->
) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing struct
s.
An Objective-C Fraction
in your example, however, is probably (one would assume) a pointer of at least type id
, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject
or NSProxy
. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C
struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.
One of the most basic operations is objc_msgSend
. When we operate on these types of objects, the Objective-C compiler interprets a dot (.
) operator or the square bracket syntax ([object method]
) as an objc_msgSend
method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.
The arrow (->
) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]->
and then bring up the method completion list, you see this:
Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]
). These particular items, however, are the C
fields that store the values of their respective Objective-C properties.
So, you can roughly think of it like this:
Dot operator on a C object
Arrow operator on a C object (pointer)
Dot operator/square brackets on an Objective-C object (pointer)
objc_msgSend
Arrow operator on an Objective-C object (pointer)
Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.