The One True Path

        Submitter: Oleg Goldshmidt

        Language: C++

        Date:        2003/07/16

I made a small informal survey, or maybe a pop quiz, last week, at two different locations. It seems that most people simply don't know what the difference between

#include <foo.h>
#include "foo.h"

is. The truth of the matter is that it is implementation-dependent (C cannot know how your filesystem is organized), but there is a clear guideline that <foo.h> is for standard system headers, while "foo.h" is for the headers from your project. 

What prompted me to ask around was a piece of code that apparently used several different rules depending on the personal point of view of the programmer who wrote this or that module, but none of the rules was correct.

Generally, the code in question had a serious bias towards

#include <foo.h>
and against
#include "foo.h"

Judging by the answers to my pop quiz part of the reason is that people think that the two forms are basically the same, but the one with quotation marks will search the current directory first, while the one with <> will not. So people like that use the <> form because it is "more efficient". This is a guess though - I didn't ask. 

The effects are generally unpredictable, and are often not visible at the preprocessing or compilation stage. Sometimes it is more subtle, and more frustrating. Consider this example.

The offending piece of code is amazingly simple:

#include <ldap.h> 

Normally, that's what you would use, so what's the problem? The problem was that the project in question included a custom (actually, pretty popular, but I am not saying anything) implementation of LDAP. It did not assume that the target platform had an independent installation of LDAP. Instead, LDAP was included in the project tree, and the appropriate preprocessor options made sure the right directory was searched.

Or at least the programmers thought so. The only reason this could work at all was that they had never tested the code on a computer with an independent installation of LDAP. The first time I tried to build the code happened to be on my Linux laptop that had OpenLDAP installed. And things immediately went haywire.

Guess what happened? Of course /usr/include/ldap.h (from OpenLDAP) was included (as #include <ldap.h>, which obviously does not depend on the -I options to the preprocessor) instead of the other, "correct" ldap.h from the project tree. What's the difference, you wonder? After all, it's supposed to be the same well-defined interface, which is all that matters as far as the header is concerned, right?

Right. Now, consider the case of a finction declared as

int Foo::bar(int something, LDAPControl** ctrl = 0);
and called as (Foo* foo is in scope)

What will happen if the OpenLDAP implementation defines

typedef struct ldapcontrol { ... } LDAPControl;
instead of
typedef struct _LDAPControl { ... } LDAPControl;

(this is the actual code, the contents of the struct are not important). Right, the linker cannot find

int Foo::bar(int,ldapcontrol**)

and the only way to find it is to run the preprocessor on Foo.cpp and the calling file and reading through all the resulting code. 

Of course, it may be regarded as a problem with both implementations of LDAP - they expose too much, while they should have hidden everything behind LDAPControl. This is a bit difficult though, because LDAPControl has to be something, and the linker will know what that "something" is. And in any case this is no excuse for being so frivolous with the preprocessor.