stdint.h

I ran into this in some of my old code today. It typedefs the different sized primitive integers (uint64, uint32, uint16, uint8, sint64, sint32, sint16, and sint8) and it declares min/max consts like max_uint64 and min_sint16. It’s a lot nicer to write uint64 than “unsigned __int64″ or “unsigned long long int”. It assumes 2′s compliment and modulo arithmetic, which is why it gets min_sint32 from (max_sint32 + 1).

// Macro to typedef sized sint and uint and declare min/max const values.
# define DECLARE_INTS( N )                                                            \
    typedef unsigned __int ## N  uint ## N ;                                          \
    typedef   signed __int ## N  sint ## N ;                                          \
    static const uint ## N  max_uint ## N  = (uint ## N) ((sint ## N) -1);            \
    static const sint ## N  max_sint ## N  = (sint ## N) ((max_uint ## N >> 1)    );  \
    static const sint ## N  min_sint ## N  = (sint ## N) ((max_uint ## N >> 1) + 1)

DECLARE_INTS( 64 );
DECLARE_INTS( 32 );
DECLARE_INTS( 16 );
DECLARE_INTS(  8 );

# undef DECLARE_INTS

Of course I prefer to just to #include <stdint.h> or <cstdint> and get typedefs like int8_t, uint64_t, int_least32_t, int_fast32_t, uintptr_t, and intmax_t, along with a bunch of min/max consts.

But Visual Studio 2008 doesn’t provide stdint.h. I can get stdint.h of course — I’ve got it now in cygwin. But I hate reaching around to there from a Visual Studio project, and I hate copying the file to my project.

So why isn’t stdint.h provided by Visual Studio? Is it because stdint.h, while part of standard C is not a part of C++? That seems kind of purist for Microsoft. Or is it because MS really wants you to use typedefs like ULONG and LONGLONG, which are not standard by the way. In fact “long long” is standard C99 but not C++. Although it probably will be next year.

(I’m not sure what they’re going to call 128-bit integers. LONGLONGLONGLONG maybe?)

Although I think uint64_t is easier to read than “unsigned long long int”, the later is more consistent with the standard literal-const suffixes and format strings.

// The suffixes and format strings are consistent with the types.
{
    long i1 = 123L;
    long long i2 = 123LL;
    unsigned long u1 = 123uL;
    unsigned long long u2 = 123uLL;

    printf( "%ld %lld %lu %llu", i1, i2, u1, u2);
}

Although there are suffixes and format strings consistent with types like uint64_t I don’t think they are standard C or C++, although they’re provided by MS.

// These suffixes are consistent too, although only i64 and ui64 are documented.
{
    __int64 i3 = 123i64;
    __int32 i4 = 123i32;
    __int16 i5 = 123i16;
    __int8  i6 = 123i8 ;
    unsigned __int64 u3 = 123ui64;
    unsigned __int32 u4 = 123ui32;
    unsigned __int16 u5 = 123ui16;
    unsigned __int8  u6 = 123ui8 ;

    // %I32d %I32u etc probably also work, at least with MS.
    printf( "%I64d %I64u", i3, u3);
}

stdint.h provides an answer to the const-suffix problem with macros like these:

#define INT16_C( x)  x
#define INT32_C( x)  x ## L
#define INT64_C( x)  x ## LL
#define UINT16_C( x) x
#define UINT32_C( x) x ## UL
#define UINT64_C( x) x ## ULL

As for the format directives, in C++ you’re supposed to avoid them anyway. Instead of sprintf(..) a C++ programmer is supposed to do this.

# include <sstream>

{
    __int64 value = ... something ...

    std::ostringstream value_stream;
    value_stream << value;
    std::string value_string = value_stream.str( );
    const char* value_buf = value_string.c_str( );
}

Of course sprintf(..) is faster because it doesn't malloc(..). If I wanted slow I'd be writing in Java.

Comments

One Response to “stdint.h”

  1. Neal on July 29th, 2008 10:20 am

    I was getting a lot of spam comments so I put in a filter. It lets you comment if you have javascript and cookies enabled in your browser. I’m not worried about the javascript requirement, but does everyone allow cookies?

    (Yeah, this comment made it past the filter!)

Leave a Reply