Search code examples
headerlocalprivatec99

Can I include local header in c99 without bloating the namespace further down the line?


Is there a way for my to include a c99 header file and only have it accessible in the header I include it in?

I am trying to create some typedefs and macros but I don't want them to bloat the namespace further down the line with it's header dependencies.

here is a example of what I mean..

// l2kdef.h

#ifndef LIN32_L2KDEF_H
#define LIN32_L2KDEF_H

//have these only accessible in this header begin
#include <stdbool.h>
#include <stdlib.h>
#include <float.h>
#include <raylib.h>
//have these only accessible in this header end

//public types below
typedef char      _Char;
typedef int8_t    _I8;
typedef int16_t   _I16;
typedef int32_t   _I32;
typedef int64_t   _I64;
typedef u_int8_t  _U8;
typedef u_int16_t _U16;
typedef u_int32_t _U32;
typedef u_int64_t _U64;
typedef float     _F32;
typedef double    _F64;
typedef size_t    _Enum;
typedef size_t    _Size;

typedef struct _Col
{
    _U8 r;
    _U8 g;
    _U8 b;
} _Col;
typedef struct _Img
{
    _U8* data;
    _U32 w;
    _U32 h;
} _Img;
typedef struct _Tex
{
    _U32 id;
    _Img img;
} _Tex;

#define bool _Bool
#define char _Char
#define i8   _I8
#define i16  _I16
#define i32  _I32
#define i64  _I64
#define u8   _U8
#define u16  _U16
#define u32  _U32
#define u64  _U64
#define f32  _F32
#define f64  _F64
#define enum _Enum
#define size _Size
#define col  _Col
#define img  _Img
#define tex  _Tex


#endif //LIN32_L2KDEF_H

Solution

  • According to the C99 standard:

    If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit.

    Thus, there is no way to prevent prior type definitions from being visible in the rest of the source file including this header file.

    The standard also states the following regarding integer types defined in stdint.h:

    The header <stdint.h> declares sets of integer types having specified widths, and defines corresponding sets of macros.

    Given that the integer types are defined as macros, you should be able to undefine them after you have used the macros in your program using #undef.

    If the objective is to force developers to use the custom types defined in this header file in lieu of the C99 types, one trick that may work is to create macros identifying the replaced types with something untranslatable after the typedef statements.

    For example, after typedef char _Char; one could place the macro #define char (++), which would force any future uses of char to be replaced with (++) by the pre-compiler. Note that the C99 standard does not restrict the use of keywords from being translated by the pre-compiler (prior to phase 7):

    The above tokens (case sensitive) are reserved (in translation phases 7 and 8) for use as keywords, and shall not be used otherwise.

    Side Notes:

    Type bool is already defined in stdbool.h and is being redefined by #define bool _Bool here.

    Several type identifiers are specified using a leading underscore. The C99 standard states:

    All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use. An alternate option may be to add a trailing underscore rather than to use a leading underscore.