10

我正在为 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;
};

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

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 反之亦然?

4

1 回答 1

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

以下类型指定了一个无符号整数类型,其属性是任何指向 void 的有效指针都可以转换为此类型,然后转换回指向 void 的指针,结果将与原始指针进行比较:

 uintptr_t

这些类型是可选的。

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

幸运的是,POSIX采取了救援措施:它确实要求对象指针和函数指针的大小相同。

2.12.3 指针类型

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

笔记:

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

于 2012-05-01T13:47:10.023 回答