tags:

views:

165

answers:

3

What's the recommended approach to typedefs for standard types in C?

For example at the start of my project I created typedefs to use the smallest types possible for their purpose. The main intention was to allow for easy modification of the types in the case where the numerical ranges used became too large for the type without having to do a global search+replace on the entire project. But after six months I'm not satisfied and think there must be a better way.

These are the types I have defined:

/*  type to be used for storing map data within
    n*n array                                   */
typedef unsigned char map_t;

/*  type to be used for storing coordinates in map.
    min 0,max 32 (MAP_W,MAP_H defaults). note: no
    longer requires signed.                     */
typedef unsigned char xy_t;

/*  type to be used for counters, ie moves_remaining
    has max 2000                                */
typedef signed int ctr_t;

/*  type to be used for storing the level number,
    requires signed.                            */
typedef signed short lvl_t;

/*  type to be used for storing contact types,
    see actions.h CONTACT                       */
typedef signed short ct_t;

/*  small unsigned type, miscellaneous          */
typedef unsigned char su_t;

/*  small signed type, miscellaneous            */
typedef signed char ss_t;

struct xy
{
    xy_t x;
    xy_t y;
};

struct scrxy
{
    int x;
    int y;
};

struct xy_offset
{
    ss_t x;
    ss_t y;
};

Some code, instead of using a signed type and checking for n < 0 && n > max_val uses an unsigned type and only checks for n > max_val where max_val is less the T_MAX although I've since discovered this behaviour is actually undefined.

Should I remove all these typedefs and use the standard types define in stdint.h instead throughout my code (the sizes have stabilized fairly well now)?

+2  A: 

I personally would typedef all these max_t etc. types in terms of stdint.h types:

typedef uint8_t map_t;

Apart from the two "miscellaneous" types, I'd use a similar approach myself - with all compiler warnings and errors regarding integer conversions and comparisons enabled.

I guess you'll need to switch programming languages if you want more precise type definitions and use Ada :)

ndim
+1 for mentioning Ada... I miss constrained types.
D.Shawley
A: 

My advice to you is that you should keep the typedefs as they are, as long as they are being used consistently. Having these typedefs may be a great help in refactoring your program in the future.

Kinopiko
+2  A: 
  • Start by finding or creating a version of <stdint.h> if your compiler doesn't support it already.
  • After that, I would recommend creating typedefs for data types based on their usage and not their size if at all possible. You seem to have a mixture of data type size (ss_t) and usage (lvl_t). This tends to become problematic as programmers will just choose one or the other arbitrarily or pick the one that they find easiest to type.
  • Remove the "_t" from the end. Global identifiers ending in _t are reserved by POSIX along with a host of other sequences.
D.Shawley
The `_t` suffix is reserved by POSIX; it's not ANSI or ISO.
Adam Rosenfield
@Adam: thanks... I guess that's why I couldn't find it in my copy of ISO then. Must have read it in the POSIX Programmer's Guide.
D.Shawley