Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting NULL pointers

Please consider the following program. Given four different pointers, it prints them as unsigned long.

#include<stdio.h>

typedef unsigned long ulong;

int main(){
    char        *pc = NULL;
    int         *pi = NULL;
    double      *pd = NULL;
    long double    *pld = NULL;
    printf("%5lu%5lu\n%5lu%5lu\n%5lu%5lu\n%5lu%5lu\n",
        (ulong)(pc + 1),(ulong)(pi + 1),
        (ulong)(pd + 1),(ulong)(pld + 1),  
        (ulong)(pc + 1),(ulong)(pld + 1)
        (ulong)(pc), (ulong)(pc));
    return 0;
}

Well, I am not totally sure that I gave the results the correct meaning:

1    4
8   16
1   16
0    0

With pc + 1 and pi + 1 we have 1 and 4 respectively. My system, most likely, assign 1 byte for a pointer to char and 4 for a pointer to int. On this base, I deduced that the program gives me the amount of memory assigned made available to these pointers.

But pc and pi return both zero. Why? If my deduction was correct, should not 1 and 4 bytes of memory be assigned in any case to pc and pi?

like image 931
Worice Avatar asked Jan 20 '26 15:01

Worice


1 Answers

Your expectation is a bit strange:

If my deduction was correct, should not 1 and 4 bytes of memory be assigned in any case to pc and pi?

There's no "memory assigned" to a pointer. A pointer is just an object containing an address. This might be an address of an actually usable object, or it might be invalid. If it's NULL, it's guaranteed to be invalid.

Representations of different pointer types are allowed to be different, although they rarely are in practice. If they are, it's guaranteed you can convert NULL of different types to each other, it will stay a null pointer. Apart from that, the compiler uses the type information associated with a pointer to compute indices. If you add 1 to a pointer pointing to a type of size 8, the actual value will increase by 8.

The following two quotes from the standard seem relevant to your question:

§6.3.2.3 p3:

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 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.

§6.3.2.3 p6:

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

So, your code is implementation defined. Converting 0 to void * gives you a null pointer, therefore it's not unreasonable that converting a null pointer to some integer type gives indeed 0, but this isn't guaranteed.

Strictly speaking, the expressions adding an offset to NULL are even undefined behavior: For pointer arithmetics to be well-defined, the result of the expression must point to an existing array element or one past that -- that's of course impossible with NULL which isn't a valid pointer in the first place.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!