I want to know if I can rely on the particular definitions of the include guards in standard headers. If I look on my system with Visual Studio I can see, for example, that stdint.h has the _STDINT
defined. My question is if I can rely on this #define
for other compilers too. Basically, is it safe for me to do something like this:
#ifndef _STDINT
typedef char int8_t;
#endif
I know this might look stupid. Why not just include stdint.h you say? Well I'm writing code which may be deployed embedded targets, which might not be happy about including certain standard c headers. However, I want to be able to use them when they are available. Therefore, I want to be able to choose in the file that has int main()
whether I want to include stdint.h or not.
You can rely on a standard library header to declare exactly (and no more than) what it is specified to declare. This means that:
If a feature is optional, the standard will specify a feature-test macro that you can check for with #if
or #ifdef
, to tell you if it is available on your platform. e.g. threads.h
is optional in C11, so the standard specifies that __STDC_NO_THREADS__
is defined to 1 if the header is not available.
If a feature is not optional, you should be able to assume it is present! If it isn't present, the compiler isn't conforming to the language version, and you'd better hope that this stuff is explicitly spelled out in the documentation, because you're into implementation-defined territory.
Many features are provided as macros, or with associated macro definitions; you can therefore test for the existence of such features independent of the whole header.
So for the case of stdint.h
, there is no feature test macro provided because the header is not optional. If it isn't present, the compiler really ought to be documenting that, and not claiming standard compliance. However, certain features within stdint.h
are optional, and are therefore testable individually with their associated macros.
For instance, the exact-width integer types described in 7.20 (int8_t
and so on) require associated macro definitions describing their maximum and minimum values (and that these macros specifically not be defined if the types are not available), so you can test for the specific availability of int8_t
by testing whether INT8_MAX
is defined after including the header.