我们可以减去NULL指针吗?

St.*_*rio 5 c pointer-arithmetic null-pointer ptrdiff-t

由于指针算术是在同一数组中定义的,我怀疑是否可以NULL从另一个数组中减去NULL。我担心的是:

//first and second can both either be from the same array 
//or be both NULL
prtdiff_t sub(void *first, void *second){
    //Do I really need this condition?
    if(!first && !second)
        return (ptrdiff_t) 0;

    return second - first;
}
Run Code Online (Sandbox Code Playgroud)

dbu*_*ush 8

不允许减去两个NULL指针。C标准的 6.5.6p9节规定

当减去两个指针时,两个指针都将指向同一数组对象的元素,或者指向数组对象的最后一个元素之后的元素;结果是两个数组元素的下标不同。 结果的大小是实现定义的,其类型(带符号整数类型)是在标头中定义的ptrdiff_t。如果结果无法在该类型的对象中表示,则该行为未定义。换句话说,如果表达式P和Q分别指向数组对象的第i个元素和第j个元素,则表达式(P)-(Q)具有值i?j,前提是该值适合类型为ptrdiff_t的对象。而且,如果表达式P指向数组对象的一个​​元素或指向数组对象的最后一个元素,而表达式Q指向同一数组对象的最后一个元素,则表达式((Q)+1) -(P)与((Q)-(P))+ 1和-((P)-((Q)+1))具有相同的值,

由于两个指针均未指向数组对象,因此行为是不确定的。

您也不能减去两个,void *因为void它是不完整的类型,并且指针减法取决于知道指向对象的大小。您可以将每个指针转换为a intptr_t并减去它们,但是这会给您指针之间的字节差,而不是索引差。

  • @PaulOgilvie这是引用:http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3 * ..得到的指针(称为空指针)保证可以比较不等于指针的指针任何对象或功能。但是,是的,这就是您只说“好吧,我的编译器足够理智地理解我想要做什么”的情况之一。 (5认同)
  • @PaulOgilvie:在语义上,“空指针值”仅保证比较不等于任何对象或函数的地址。不能保证它是地址0(某些较早的系统使用0xDEADBEEF作为空指针值)。它也被视为*无效*指针值(尝试取消引用它的行为是不确定的)。 (3认同)
  • *在许多实现中,`intptr_t`的差将是字节差,但是将指针转换为整数的结果是实现定义的,因此不能保证结果。 (2认同)

Bat*_*eba 6

不,您不能这样做:两个指针之间的区别仅针对指向同一数组的元素或指向末尾的元素的指针定义。(为此,一个对象计为单个元素数组)。

(intptr_t)second - (intptr_t)first 是有效的。

  • 如我所说,@ St.Antario是实现定义的,因为将指针值转换为整数类型的效果是实现定义的,而与所涉及的特定整数类型无关。`intptr_t`是可选的是一个单独的问题。 (2认同)