是指减去两个空指针的行为? [英] Is the behavior of subtracting two NULL pointers defined?

查看:157
本文介绍了是指减去两个空指针的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

时定义的两个非空指针变量的差异(每C99和/或C ++ 98),如果他们都 NULL 价值?

例如,假设我有一个缓冲结构,看起来像这样:

 结构BUF {
  字符* BUF;
  字符* PWRITE;
  字符* $ P $垫;
}前;

说, ex.buf 指向数组或一些malloc分配内存。如果我的code始终确保 PWRITE 这个数组中的$ P $垫点,或过去吧,那么我相当有信心, ex.pwrite - 前$ p $垫将永远被定义。但是,如果 PWRITE $ P $垫都是NULL。我只是希望减去两个被定义为(ptrdiff_t的)0 或不符合严格code需要测试的指针NULL?请注意,我唯一感兴趣的情况是当的两个的指针是NULL(其中重presents缓冲区未初始化的情况下)。原因与给定preceding假设成立一个完全符合可用功能做的事:

 为size_t buf_avail(const的结构s_buf * B)
{
    返回B-> PWRITE - B-> $ P $垫;
}


解决方案

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


  

7)为这些操作符的目的,一个指向的对象是不是一个一个元件
  阵列的行为相同的指针长度的一个的阵列与第一元件
  类型对象作为其元素的类型。


  
  

[...]


  
  

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


和§6.3.2.3/ 3说:


  

值为0,或者这样的前pression投整型常量前pression键入
  空隙* ,被称为空指针恒定 55)如果空指针常数转换为指针类型,所得到的指针,被称为的空指针的,是保证比较不等的指针任何对象或功能。


所以,因为一个空指针不等于任何对象,它违反了6.5.6 / 9 preconditions,所以这是不确定的行为。但在实用性,我愿意打赌,pretty多少每个编译器将返回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的

Is the difference of two non-void pointer variables defined (per C99 and/or C++98) if they are both NULL valued?

For instance, say I have a buffer structure that looks like this:

struct buf {
  char *buf;
  char *pwrite;
  char *pread;
} ex;

Say, ex.buf points to an array or some malloc'ed memory. If my code always ensures that pwrite and pread point within that array or one past it, then I am fairly confident that ex.pwrite - ex.pread will always be defined. However, what if pwrite and pread are both NULL. Can I just expect subtracting the two is defined as (ptrdiff_t)0 or does strictly compliant code need to test the pointers for NULL? Note that the only case I am interested in is when both pointers are NULL (which represents a buffer not initialized case). The reason has to do with a fully compliant "available" function given the preceding assumptions are met:

size_t buf_avail(const struct s_buf *b)
{     
    return b->pwrite - b->pread;
}

解决方案

In C99, it's technically undefined behavior. C99 §6.5.6 says:

7) For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

[...]

9) When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. [...]

And §6.3.2.3/3 says:

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.

So since a null pointer is unequal to any object, it violates the preconditions of 6.5.6/9, so it's undefined behavior. But in practicality, I'd be willing to bet that pretty much every compiler will return a result of 0 without any ill side effects.

In C89, it's also undefined behavior, though the wording of the standard is slightly different.

C++03, on the other hand, does have defined behavior in this instance. The standard makes a special exception for subtracting two null pointers. C++03 §5.7/7 says:

If the value 0 is added to or subtracted from a pointer value, the result compares equal to the original pointer value. If two pointers point to the same object or both point one past the end of the same array or both are null, and the two pointers are subtracted, the result compares equal to the value 0 converted to the type ptrdiff_t.

C++11 (as well as the latest draft of C++14, n3690) have identical wording to C++03, with just the minor change of std::ptrdiff_t in place of ptrdiff_t.

这篇关于是指减去两个空指针的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆