如果两个非空指针变量都是NULL值,是否定义了它们的差异(根据C99和/或C++98)?

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

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

比如说,ex.buf个点指向一个数组或某个malloc'ed内存.如果我的代码总是确保pwritepread点在该数组中,或者超过它一点,那么我很有信心ex.pwrite - ex.pread总是被定义的.然而,如果pwritepread都为空呢.我能期望减go 定义为(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) 在这些运算符中,指向不是

[...]

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

并且§6.3.2.3/3说:

值为0的整型常量表达式,或转换为类型的此类表达式

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

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

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

如果在指针值上加上或减go 值0,结果将与原始指针值进行比较.如果两个指针指向同一个对象,或者两个指针都指向同一数组的末尾,或者两个指针都为空,并且两个指针相减,则结果比较等于转换为类型ptrdiff_t的值0.

C++11(以及最新的C++14草案,n3690)与C++03有相同的措辞,只是将ptrdiff_t改为std::ptrdiff_t.

C++相关问答推荐

无根生成树中的同步领导人选举宣布多个获胜者

在C、Linux中同步进程

在C中使用动态内存分配找到最小的负数

为什么在C中二维字符数组会有这样的行为?

如何使用低级C++写出数值

如果包含路径不存在,我的编译器可以被配置为出错吗?(GCC、MSVC)

如何跨平台处理UTF-16字符串?

FRIDA-服务器成为端口扫描的目标?

添加函数会 destruct 嵌入式C代码(无IDE)

这个空指针类型的转换是有效代码还是恶意代码?

使用%f格式说明符打印整数值

仅从限制指针参数声明推断非混叠

如何使这个While循环在新行上结束

为什么我的半数组测试和奇数组测试不起作用?(我使用Assert进行调试)

OMP并行嵌套循环

存储和访问指向 struct 的指针数组

C语言中的指针和多维数组

如何在C中计算包含递增和递减运算符的逻辑表达式?

%g浮点表示的最大字符串长度是多少?

获取 struct 中匿名 struct 的大小