Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is intptr_t a signed counterpart of uintptr_t (and vice versa)?

I'm developing some tests for the add_signed MPL class that converts the type to its signed counterpart. It is defined as follows:

template<class T>
struct add_signed { 
    typedef T type;
};

template<>
struct add_signed<std::uint8_t> { 
    typedef std::int8_t type;
};

template<>
struct add_signed<std::uint16_t> { 
    typedef std::int16_t type;
};

template<>
struct add_signed<std::uint32_t> { 
    typedef std::int32_t type;
};

template<>
struct add_signed<std::uint64_t> { 
    typedef std::int64_t type;
};

While testing on different types I noticed that the following evaluates to true:

std::is_same<add_signed<uintptr_t>::type, intptr_t>::value  // true

Similarly for the add_unsigned MPL class, the following code evaluates to true:

std::is_same<add_unsigned<intptr_t>::type, uintptr_t>::value  // true

My compiler is MSVC 2010.

So the question is - can we assume that in all (sane) compilers signing intptr_t will produce uintptr_t and vice versa?

like image 723
Bartłomiej Siwek Avatar asked May 01 '12 13:05

Bartłomiej Siwek


1 Answers

The types intptr_t and uintptr_t are optional in ISO/IEC 9899:1999 (C99), but where one is implemented, so is the other. All signed types have an unsigned counterpart of the same size, and vice versa.

§7.18.1 Integer types

When typedef names differing only in the absence or presence of the initial u are defined, they shall denote corresponding signed and unsigned types as described in 6.2.5; an implementation providing one of these corresponding types shall also provide the other.

...

§7.18.1.4 Integer types capable of holding object pointers

The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

intptr_t

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

 uintptr_t

These types are optional.

Note that within the meaning of the C standard, functions are not objects; it is not guaranteed by the C standard that uintptr_t can hold a function pointer.

Fortunately, POSIX steps to the rescue: it does require that object pointers and function pointers are the same size.

2.12.3 Pointer Types

All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

Note:

The ISO C standard does not require this, but it is required for POSIX conformance.

like image 112
Jonathan Leffler Avatar answered Nov 10 '22 02:11

Jonathan Leffler