views:

739

answers:

6

I need to use system-specific functions, e.g. ftello() (defined in stdio.h as per POSIX standard). I also need to use standard C++ features, e.g. std::sprintf() (defined in cstdio, as per ISO C++ standard).

AFAIK, including only <cstdio> doesn't guarantee defining non-standard-C++ stuff, so I guess I have to include both. I've read a long time ago that (for example) with gcc there may be problems with the include file order.

So, what is the correct order for including both <cstdio> and <stdio.h>? I'm looking for a solution which is as cross-platform as possible (at least for gcc, suncc, intel C++/linux and mingw).

Thanks!

+2  A: 

For system header files the order of inclusion should generally be not a source of errors.

For other header files have a look at the similar question here at SO.

Kosi2801
Thanks for the answer.I think I found a similar issue here:http://gcc.gnu.org/ml/libstdc++/2003-01/msg00210.htmlI actually stumbled across it a while ago, but I don't remember the details. The headers were definitely system through.While this is a system / compiler issue, what I was asking is that maybe somebody knows a tried method of dealing with this kind of stuff.
Alex
A: 

From what I can tell, ftello() and sprintf() are both included in stdio.h.

Include order may matter for non-standard headers, you have to check the dependency structures to find out which is dependent on the other, and include them in the correct order.

For this reason, dependencies of include files should be included in the include file, and not rely on the "user" to ensure they are properly included.

Sev
Yes, ftello() and sprintf() are from stdio.h, but I'm talking about std::sprintf(), which may or may not be the same as sprintf(). In fact, it probably isn't, because sprintf() is usually a compiler-defined macro, while std::sprintf() is guaranteed to be a function (which you can take address of).So, I need to use ftello() from stdio.h and std::sprintf() from cstdio.Both are from standard include files, but since these two files have a special relationship, I don't know which is the correct order that works reliably on various compiler / OS combinations.
Alex
+2  A: 

I don't know of any true rule, however generally speaking I include the lower level system libraries before the higher level libraries.

So in this case stdio.h is a C header and (in my imagination) is closer to the machine, and <cstdio> is higher level, C++ Standard Library which I imagine to be more abstracted.

I tend to include stdio.h before cstdio myself, but I don't know of an exact reasoning to support that rationale.

John Weldon
A: 

You're worrying for no good reason. The contents of <cstdio> are "as if by inclusion" those of <stdio.h> (17.4.1.2 Headers/4). The declarations and definitions (but not the macro's) are in namespace std, though.

So you might need to write std::ftello(). For improved portability, throw in a using std::ftello; and you don't need to care about that either.

MSalters
ftello() is not in C++ standard, and there is no ftello() in std namespace (at least in gcc's libstdc++).Thanks anyway!
Alex
That's exactly my point. The C++ standard doesn't specify exactly what is in stdio.h. It merely says that cstdio contains whatever is in stdio.h, but in namespace std. If libstdc++ puts ftello in stdio.h but not in cstdio, it violates 17.4.1.2.
MSalters
A: 

OK, after some more reasearch I finally came to a conclusion that including the C++ header first, C header later is the correct thing to do. For example, consider the following C++0x header (from gcc):

/usr/include/c++/4.3/tr1_impl/cstdint:


// ...
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include_next <stdint.h>
// ...

What it does is that it defines two C99 macros, and only then includes the C99 stdint.h header. The reason is that in C99, some of the features of stdint.h are optional, and only available if those macros are defined. However, in C++0x, all stdint.h features are mandatory. Now, if I included the C99 stdint.h first, cstdint later, I wouldn't get the mandatory C++0x features because of the header guards in stdint.h. One could argue that this is the compiler vendor's fault, but that would be incorrect. stdint.h is a system-bundled header (from glibc in this case), which is a C99 header and doesn't know anything about C++0x (it can be an old system, after all) or gcc. The compiler can't really fix all the system headers (in this case to always enable those features in C++ mode), yet it has to provide C++0x support on these systems, so the vendor uses this workaround instead.

Alex
A: 

I put the most specific stuff at the top, and the least specific stuff at the bottom. For an source file for example it would like this:

  1. Precompiled header, if any
  2. Header for this source file
  3. Project includes
  4. Most specific libraries, for instance libraries in this project, or company libraries
  5. Least specific libraries, such as "system" libraries like boost, or SDL
  6. Standard C++
  7. Standard C
  8. Operating system headers

My justification is that the more specific headers will often include more generic headers, and want to modify them via macros. If these are already included, include guards, or default macro values will clobber the behaviour for system libraries.

Another justification is that this ordering prevents you from "hiding" dependencies from other headers, that is those headers won't stand alone when included from other source files, as they've always had system libraries included before themselves.

Matt Joiner