Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we subtract NULL pointers?

Since pointer arithmetic is defined within the same array I'm in doubt if we can subtract NULL from another NULL. I'm concerned about the implementation of:

//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;
}

Note: This question about C. If you are looking for C++ question, it is here (the answer is different!). There is also common question for both C and C++.

like image 272
St.Antario Avatar asked Apr 18 '19 13:04

St.Antario


Video Answer


2 Answers

Subtracting two NULL pointers is not allowed. Section 6.5.6p9 of the C standard states:

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. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the header. If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively, the i -th and j -th elements of an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t . Moreover, if the expression P points either to an element of an array object or one past the last element of an array object, and the expression Q points to the last element of the same array object, the expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)) , and has the value zero if the expression P points one past the last element of the array object, even though the expression (Q)+1 does not point to an element of the array object.

Because neither pointer points to an array object, the behavior is undefined.

You also can't subtract two void * because void is an incomplete type, and pointer subtraction depends on knowing the size of the pointed-to object. You could cast each pointer to a intptr_t and subtract those, however that would give you the byte difference between the pointers, not the index difference.

like image 96
dbush Avatar answered Oct 07 '22 05:10

dbush


No you can't do this: the difference between two pointers is only defined for pointers that point to elements of the same array, or one past the end. (For this purpose an object counts as a single element array).

(intptr_t)second - (intptr_t)first is valid though.

like image 7
Bathsheba Avatar answered Oct 07 '22 05:10

Bathsheba