Type of unsigned long is different from uint32_t and uint64_t on Windows (VS2010)

tbleher picture tbleher · Jul 23, 2012 · Viewed 26.2k times · Source

On Visual Studio 2010 under Windows 7, 32bit, unsigned long seems to be a distinct type from both uint32_t and uint64_t. See the following test program:

#include <stdint.h>
#include <stdio.h>

template<class T, class U>
struct is_same_type
{
    static const bool value = false;
};
template<class T>
struct is_same_type<T, T>
{
    static const bool value = true;
};

#define TO_STRING(arg)        TO_STRING_IMPL(arg)
#define TO_STRING_IMPL(arg)   #arg

#define PRINT_SAME_TYPE(type1, type2) printf("%s (size=%d) %s %s (size=%d)\n", \
    TO_STRING(type1), int(sizeof(type1)), \
    is_same_type<type1, type2>::value ? "==" : "!=", \
    TO_STRING(type2), int(sizeof(type2)))


int main(int /*argc*/, const char* /*argv*/[])
{
    PRINT_SAME_TYPE(uint32_t, unsigned long);
    PRINT_SAME_TYPE(uint64_t, unsigned long);
    return 0;
}

I'd expect it to print either

uint32_t (size=4) != unsigned long (size=8)
uint64_t (size=8) == unsigned long (size=8)

(which I get on x86_64 Linux) or

uint32_t (size=4) == unsigned long (size=4)
uint64_t (size=8) != unsigned long (size=4)

assuming of course that long is not longer than 64bits.

On Windows however, I get the baffling

uint32_t (size=4) != unsigned long (size=4)
uint64_t (size=8) != unsigned long (size=4)

which means that there are two distinct 32bit unsigned types. Is this allowed by the C++ standard? Or is this a bug in the Visual C++ compiler?

Answer

James McNellis picture James McNellis · Jul 23, 2012

There are two distinct 32-bit, unsigned types

Yes, there are. Both int and long are represented by 32 bits.

Is this allowed by the C++ standard?

Yes. The specification states (C++11 §3.9.1[basic.fundamental]/2):

There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.

For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type...each of which occupies the same amount of storage and has the same alignment requirements as the corresponding signed integer type

Note that despite the fact that int and long are represented by the same number of bits, they are still different types (so, for example, they are treated differently during overload resolution).