5

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;
}
  • 4
    @St.Antario Actually you have explained it yourself and likely have your reference ... – Eugene Sh. Apr 18 at 14:01
  • 2
    Well, checking here for NULL has a little help as any other invalid pointer will break it equally. – Eugene Sh. Apr 18 at 14:03
  • 2
    @St.Antario while I was looking for references two answers posted. :p – Harshit Agrawal Apr 18 at 14:04
  • 1
    @St.Antario So if NULL is defined as an integer constant expression you can subtract NULL from NULL, but not that is not portable because it might not be (and usually isn't) defined as an integer constant expression. – Ian Abbott Apr 18 at 14:12
  • 2
    Even if NULL is defined as an integer 0, then after assigning char *a = NULL; char *b = NULL;, then the subtraction a - b is still illegal. – Ian Abbott Apr 18 at 14:19
8

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.

  • 2
    On many implementations the intptr_t difference would be a byte difference, but the result of converting a pointer to an integer is implementation-defined, so that result is not guaranteed. – John Bollinger Apr 18 at 14:14
  • Technically NULL is a valid adress and is the first byte of addressable memory. Hence it can point to an array object and so you can subtract NULL from NULL. It s only the memory management hardware that has been told that for applications NULL is not a valid adress and upon dereferencing it should throw an exception. Example: interrupt vectors start at zero. – Paul Ogilvie Apr 18 at 14:18
  • @PaulOgilvie I believe NULL is defined not to be a valid address by the standard (reference needed..). The case on a specific architecture where the address 0 is actually valid (and having NULL representation the same as pointer to this address) is making the corresponding architecture/toolchain combo non-compliant. – Eugene Sh. Apr 18 at 14:21
  • 5
    @PaulOgilvie Here is the citation: port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3 ..the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.. But yeah, that would be one of these corner cases where you just say "well, my compiler is sane enough to understand what I want to do".. – Eugene Sh. Apr 18 at 14:25
  • 3
    @PaulOgilvie: Semantically, the null pointer value is only guaranteed to compare unequal to the address of any object or function. It is not guaranteed to be address 0 (some older systems used 0xDEADBEEF as the null pointer value). It is also considered an invalid pointer value (the behavior on attempting to dereference it is undefined). – John Bode Apr 18 at 14:25
6

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.

  • The integer difference is definitely valid, but its meaning is implementation-defined (provided there is no overflow), on account of the result of converting pointers to integers being implementation defined. – John Bollinger Apr 18 at 14:10
  • @JohnBollinger Implementation-defined in the sense of intptr_t is not required to be supported? Or in some another way? – St.Antario Apr 18 at 14:14
  • 2
    As I said, @St.Antario, implementation-defined because the effect of converting a pointer value to an integer type is implementation-defined, regardless of the particular integer type involved. That intptr_t is optional is a separate issue. – John Bollinger Apr 18 at 14:18
0

The simple answer is NO, YOU CAN'T SUBTRACT A NULL FROM ANOTHER NULL.

I think you misunderstood this definition:

NULL is clearly defined as: An integer constant expression with the value 0, or such an expression cast to type void, is called a null pointer constant. So I used to think that we could subtract one 0 from another 0.

Now, As for now let's take GOOGLE's Definition of NULL

Null means having no value; in other words null is zero, like if you put so little sugar in your coffee that it's practically null. Null also means invalid. From the Latin nullus, meaning "not any," poor, powerless null is not actually there at all.

Clearly, it states that null has no value. Think of it as you are trying to subtract nothing from nothing.

Now let's take it in other words, null is zero (if and only if defined value) you can subtract it for sure (but not you can do something like char *ab = NULL, char *aa= NULL and then performing subtraction like ab-aa is still illegal)

But no one can actually predict the value for null so, when you are unable to get the value you are not able to perform any operation(like subtraction, addition, etc.) on that.

-2

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.

But there is no such provision for C.

  • So C++ handles your case. – Ôrel Apr 18 at 14:05
  • 9
    This question is tagged C, not C++. – dbush Apr 18 at 14:07
  • 2
    If you add something like "..but there is no such a provision for C" and a conclusion, your answer might become considered as good one. – Eugene Sh. Apr 18 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.