如果两个非 void 指针变量都是定义的(根据 C99 和/或 C++98),它们之间的区别是NULL
valued?
例如,假设我有一个如下所示的缓冲区结构:
struct buf {
char *buf;
char *pwrite;
char *pread;
} ex;
Say, ex.buf
指向数组或某些分配的内存。如果我的代码总是确保pwrite
and pread
指向该数组内或过去的一个,那么我相当有信心ex.pwrite - ex.pread
总是会被定义。然而,如果pwrite
and pread
都是 NULL。我可以期望将两者相减定义为(ptrdiff_t)0
或者严格兼容的代码是否需要测试指针是否为 NULL?请注意,我唯一感兴趣的情况是both指针为 NULL(表示缓冲区未初始化的情况)。原因与完全兼容的“可用”功能有关,前提是满足前面的假设:
size_t buf_avail(const struct s_buf *b)
{
return b->pwrite - b->pread;
}
在 C99 中,这在技术上是未定义的行为。 C99 §6.5.6 说:
7) 就这些运算符而言,指向不是元素元素的对象的指针
数组的行为与指向长度为 1 的数组的第一个元素的指针相同
对象的类型作为其元素类型。
[...]
9) 当两个指针相减时,两个指针都指向同一个数组对象的元素,
或超过数组对象的最后一个元素;结果是差异
两个数组元素的下标。 [...]
§6.3.2.3/3 说:
An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
因此,由于空指针不等于任何对象,因此它违反了 6.5.6/9 的先决条件,因此它是未定义的行为。但实际上,我愿意打赌几乎每个编译器都会返回 0 结果,而不会产生任何不良副作用。
在 C89 中,这也是未定义的行为,尽管标准的措辞略有不同。
另一方面,C++03 在这种情况下确实有定义的行为。该标准对减去两个空指针有一个特殊的例外。 C++03 §5.7/7 说:
如果将值 0 添加到指针值或从指针值中减去值,则比较结果等于原始指针值。如果两个指针指向同一个对象,或者都指向同一个数组的末尾,或者都为 null,则将两个指针相减,结果比较等于转换为类型的值 0ptrdiff_t
.
C++11(以及 C++14 的最新草案,n3690)与 C++03 具有相同的措辞,只有细微的变化std::ptrdiff_t
代替ptrdiff_t
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)