2

假设我有两个指针:

char* p1 = nullptr;
char* p2 = std::malloc( 4 );
std::size_t offset = p2 - p1;

以这种方式抵消是否安全?到目前为止,它在我的电脑上运行良好。但我想知道偏移量是否会超过 size_t 的最大数量,从而导致此方法失败?

4

3 回答 3

6

这是未定义的行为,来自草案 C++ 标准部分5.7 Additive operator

当两个指向同一个数组对象的元素的指针相减时,结果就是两个数组元素的下标之差。结果的类型是实现定义的有符号整数类型;此类型应与标头 (18.2) 中定义为 std::ptrdiff_t 的类型相同。[...]除非两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,否则行为是未定义的。82

同样正如参考文献所述,结果std::ptrdiff_t不是size_t.

另一方面,您可以添加或减去第70段中涵盖的值:

如果将值 0 添加到指针值或从指针值中减去,则结果比较等于原始指针值。如果两个指针指向同一个对象,或者都指向同一个数组末尾的后一位,或者都为空,并且这两个指针相减,则结果比较等于转换为 std::ptrdiff_t 类型的值 0。

如果要将指针转换为整数值,则应使用intptr_t 或 uinitptr_t

intptr_t   integer type capable of holding a pointer
uintptr_t  unsigned integer type capable of holding a pointer

例如:

uintptr_t ip = reinterpret_cast<uintptr_t>( p2 ) ;
于 2014-07-22T14:26:35.957 回答
3

除了 Wojtek 的回答之外,指针运算可以而且应该只在相关指针之间进行。例如,如果您有 eg char* p3 = p2 + 4,那么您可以p3 - p2获取两个指针之间的差异,这是合法的。

但是,像

char* p4 = new char[4];
std::cout << p4 - p2 << '\n';

不合法,因为相关。p2p4

于 2014-07-22T14:26:25.020 回答
3

不,这不安全。基本上你可以对空指针做的唯一事情就是将它与另一个指针进行比较。至于加法和减法,一个空指针只能加或减零,然后减去两个空指针——这在泛型编程中可能很有用。您的情况是未定义的行为。

于 2014-07-22T14:24:50.413 回答