intptr_t是uintptr_t的签名对应物(反之亦然)?

时间:2012-05-01 13:25:00

标签: c++ c++11 metaprogramming

我正在为add_signed MPL类开发一些测试,它将类型转换为已签名的对应类型。它的定义如下:

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;
};

在对不同类型进行测试时,我注意到以下评估为true:

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

对于add_unsigned MPL类,以下代码的计算结果为true:

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

我的编译器是MSVC 2010。

所以问题是 - 我们可以假设在所有(理智的)编译器中签名intptr_t会产生uintptr_t,反之亦然吗?

1 个答案:

答案 0 :(得分:19)

类型intptr_tuintptr_t在ISO / IEC 9899:1999(C99)中是可选的,但是其中一个是实现的,另一个是实现的。所有签名类型都具有相同大小的无符号副本,反之亦然。

  

§7.18.1整数类型

     

当typedef名称仅在初始u不存在或存在时有所不同时,它们应表示相应的有符号和无符号类型,如6.2.5中所述;提供这些相应类型之一的实现也应提供另一种。

     

...

     

§7.18.1.4能够保存对象指针的整数类型

     

以下类型指定带有任何有效属性的有符号整数类型   指向void的指针可以转换为这种类型,然后转换回指向void的指针,   并且结果将与原始指针进行比较:

intptr_t
     

以下类型指定无符号整数类型,其属性为any   指向void的指针可以转换为这种类型,然后转换回指向void的指针,   并且结果将与原始指针进行比较:

 uintptr_t
     

这些类型是可选的。

请注意,在C标准的含义范围内,函数不是对象; C标准不保证uintptr_t可以保存函数指针。

幸运的是,POSIX步骤拯救:它确实需要对象指针和函数指针的大小相同。

  

2.12.3指针类型

     

所有函数指针类型应与void的类型指针具有相同的表示形式。将函数指针转换为void *不得改变表示。这种转换产生的void *值可以使用显式转换转换回原始函数指针类型,而不会丢失信息。

     

注意:

     

ISO C标准不要求这样做,但它是POSIX一致性所必需的。