Question

This question concerns the various types that need to be defined in the required headers of the POSIX/SUS standard.

Some types needs to be defined in many header files, and I'm wondering what's the correct and compliant way of achieving this.

For instance, look at the <time.h> header specification:

Inclusion of the header may make visible all symbols from the <signal.h> header.

This is straightforward, <signal.h> is included from <time.h>.

Now what about this:

The clock_t, size_t, time_t, clockid_t, and timer_t types shall be defined as described in <sys/types.h>.

As I understand it, it means we can't simply include <sys/types.h> from <time.h>, as this would expose more symbols than required.

So can anyone confirm this?
Would it break the standard compliance to include <sys/types.h>?

If so, I think the best solution is to create a specific header for each type, so a particular type can be made visible from anywhere, without worrying about other symbols.
Is there any other good solution?

And last thing, what about the types from the C standard?
Lots of types in the POSIX/SUS specification are integral types, and may need to have fixed width.

So would it be ok for the standard to include <stdint.h> from a specific header, or would it break the compliance?

Was it helpful?

Solution

You are right that exposing unwanted types and declarations from additional headers would be non-conforming.

One trivial (but, in terms of time the preprocessor spends opening files, expensive) solution is to have a separate header for each type, and whenever you need, for example, time_t, do:

#include <types/time_t.h>

Of course types/time_t.h would have the appropriate multiple-inclusion guards.

There are many other ways of achieving the same. The approach glibc and gcc use is to have special "needed" macros you can define before including a header that asks it to do nothing but provide one or more types. This solution is also very expensive, probably moreso than the above, because it breaks compilers' heuristics for multiple-inclusion guards. The compiler can't elide repeated inclusions; it has to parse the file each time it's included.

The way we do it in musl is to have a single file, bits/alltypes.h, which includes the definitions of all types which are needed by multiple headers and macros to control which are exposed. It's generated by a simple sed script that hides all the macro logic:

OTHER TIPS

Upon reading this question i opened the couldn't resist checking this up in THE largest UNIX compliant (strictly though, only "UNIX-like") open-source project of all time - Linux Kernel (which is again almost always worried about standard compliance nowadays).


A sample implementation :

The time.h header will define a few internal flags and then include the types.h which defines ALL the types albeit within #ifdefs that check whether some internal flag is defined.

So this boils down to the following :

  1. Define modular headers like time.h
  2. #define the relevant internal flags to establish the context.
  3. Include the "internal" headers that provide dependencies.
  4. Implement the "internal" headers such that they selectively expose functionality based upon the context in which they are #include-ed.

This way modular headers can be provided for inclusion without worrying about accidentally exposing more symbols than required.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top