是否定义了减去两个NULL指针的行为?

Joh*_*ebs 75 c c++ c99 c89

是否定义了两个非void指针变量(根据C99和/或C++ 98)的差异NULL?

例如,假设我有一个如下所示的缓冲区结构:

struct buf {
  char *buf;
  char *pwrite;
  char *pread;
} ex;
Run Code Online (Sandbox Code Playgroud)

比如说,ex.buf指向一个数组或一些malloc的内存.如果我的代码始终保证pwrite和pread点阵列中或一个过去,然后我相当有信心,ex.pwrite - ex.pread总是被定义.但是,如果pwrite和pread都是NULL.我可以只期望减去两个定义为(ptrdiff_t)0或严格兼容的代码需要测试指针为NULL吗?请注意,我感兴趣的唯一情况是两个指针都是NULL(表示缓冲区未初始化的情况).原因在于满足前面的假设,完全符合"可用"功能:

size_t buf_avail(const struct s_buf *b)
{     
    return b->pwrite - b->pread;
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*eld 96

在C99中,它在技术上是未定义的行为.C99§6.5.6说:

7)出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.

[...]

9)当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异.[...]

§6.3.2.3/ 3说:

值为0的整型常量表达式或此类表达式转换为类型 void *称为空指针常量.55)如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较.

因此,由于空指针与任何对象不相等,它违反了6.5.6/9的前提条件,因此它是未定义的行为.但实际上,我愿意打赌,几乎每个编译器都会返回0的结果而没有任何不良副作用.

在C89中,它也是未定义的行为,尽管标准的措辞略有不同.

另一方面,C++ 03确实在这个实例中定义了行为.该标准为减去两个空指针做了一个特殊的例外.C++03§5.7/ 7说:

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

C++ 11(以及C++ 14的最新草案,n3690)与C++ 03具有相同的措辞,只是std::ptrdiff_t代替了微小的变化ptrdiff_t.

  • 由于完整性,这是目前最好的答案. (14认同)

Pub*_*bby 36

我在C++标准(5.7 [expr.add]/7)中找到了这个:

如果两个指针都为空,并且减去了两个指针,则结果比较等于转换为类型std :: ptrdiff_t的值0

正如其他人所说,C99要求两个指针之间的加/减是同一个数组对象.NULL不指向有效对象,这就是为什么不能在减法中使用它.

  • +1:有趣,因此C++明确定义了这种行为,而C则没有. (4认同)

Jen*_*edt 23

编辑:这个答案仅对C有效,我回答时没有看到C++标签.

不,指针算法仅允许指向同一对象内的指针.由于C标准的定义,空指针不指向任何对象,因此这是未定义的行为.

(虽然,我猜任何合理的编译器都会返回0它,但是谁知道.)

  • 哇,从未想过这个蹩脚的问题会触及C/C++规范的差异. (8认同)
  • 这是不正确的.参见5.7 [expr.add]/7:"如果两个指针指向同一个对象,或者两个指针都指向同一个数组的末尾或者**都是空**,并且减去了两个指针,则结果比较相等将值0转换为`std :: ptrdiff_t`类型." (5认同)
  • @Jens:为什么?SO是社区编辑的网站. (5认同)
  • @Jens:常见问题解答和网站管理员鼓励我们编辑答案,如果我们能让它们更好.你现在的答案比以前更好.我并不打算冒犯,老实说,鉴于该网站的政策,我认为你不合适*被冒犯.请参阅:http://stackoverflow.com/privileges/edit (3认同)
  • Jens,通常我会同意你的看法.我尝试永远不要编辑别人的答案,但要指出我对评论的分歧 - 更少的羽毛被惹恼,他们可能会学到一些东西.或许我错了,而我的编辑会适得其反.但在这种情况下,我认为约翰的编辑是合理的,因为你的回答是最高的,但显然不是100%正确.在不考虑替代方案的情况下,有必要让人们不要"堆积"到正确的答案. (2认同)