Remember how we’ve talked about Objective-C being an extension to the C Programming Language?
In the C Programming Languages if you want to use the functionality provided in a library within your source files you would use a pre-processor instruction called #include
.
This pre-process directive works by instructing the compiler (or more accurately a part of the compiler called the pre-processor) to substitute the contents a referenced header file in place of the line in your source code containing the #include
statement. It does this prior to compilation of your code and also does it blindly, no questions asked. It is this lack of checking that can often lead to a problems in C, problems that often stem from something called recursive includes.
Imagine the situation where you have two files, myheader.h
and yourheader.h
. In myheader.h
we have the following code:
#include "yourheader.h"
// A comment in myheader.h
and in yourheader.h
you have this code:
#include "myheader.h"
// A comment in yourheader.h
(Note: Granted this is a bit of a contrived example and as written neither file would need to include each other as it stands but go with it for now – I’m trying to illustrate a point).
Neither of these header files are wrong on their own. But what happens when you pass them to the compiler?
Lets just look at myheader.h
first.
As we’ve talked about in other posts, the first thing the compiler does when you ask it to build your source code is to search through your source code for any pre-processor directives and perform whatever instructions it finds.
As we’ve already talked about, in the case of the #include
pre-processor directive, this means substituting the contents of the specified header file into your source code.
If we apply that logic to our header file above, lets take a look at the new contents of the myheader.h
file once the pre-processing is complete:
#include "myheader.h"
// A comment in yourheader.h
// A comment in myheader.h
See how the the #include "yourheader.h"
line has been replaced with the contents from myheader.h
?
Now on the face of it the new contents of the myheader.h
file looks alright doesn’t it? Well, the answer is: sort of.
Notice that there is still that #include "myheader.h"
statement?
As we’ve seen just now, this tells the compiler that you want it to include the contents of the myheader.h
file. So what happens?
Well, the compiler does it’s pre-processing of course. It takes the current contents of the myheader.h
file and substitutes its contents in place of the #include "myheader.h"
line, no questions asked.
Can you see where this is going? Maybe checking out the new contents of the myheader.h
file will help?:
#include "myheader.h"
// A comment in yourheader.h
// A comment in myheader.h
// A comment in yourheader.h
// A comment in myheader.h
As you can see, we’ve still got a #include "myheader.h"
line. Want to go again?
Now I’m not going to bore you by going around this over and over but by now you should see the problem. This is what we call a recursive include problem.
The compiler will continue to try to perform its pre-processing on the myheader.h
file, gradually eating up more and more memory and more and more processor time until eventually it all falls in a big heap with steam comes out of its ears (ok I invented the last bit but trust me it’s not a good thing).
In the C Programming language, this problem has been recognized for years. To get around it you will often see C source code written in the C Programming Language all sorts of pre-processor directives such as #ifndef
and #define
(we’re not going to go into these just now) to work around this problem but in the world of Objective-C we’re lucky.
Instead of #include
we have the option of using #import
.
The #import
directive in Objective-C is smart and a step beyond simply using #include
.
Where the #import
directive differs is that when the compiler encounters it as part of it’s pre-processing, it instructs the compiler to use some intelligence when it does it’s file substitution.
In doing so the compiler first checks to see whether the header file that is being referenced has already been included before. If it has, it simply ignores the pre-processor directive.
That’s it.
That one simple check is enough to avoid the recursive header include nightmare that we’ve just been talking about.
It’s a nice language Objective-C.
Image credit: http://flic.kr/p/9bGxf6