Search code examples
cpointersvariablesmemory

Unusually Large values and negative values of addresses of a variable


So I was learning and practicing the concept of Pointers and addresses of variables in C language. But there is one thing that is making me curious. The code that I ran is-

    #include <stdio.h>

    int main()
    {
       int *p, n;
       p = &n;
       int *c = NULL;

       printf("Address of variable = %p\n", p);
       printf("Address of variable = %lu\n", p);
       printf("Address of c variable = %lu\n", c);
       return 0;
    }

I am sure that this code is correct to print addresses and the output I got was-

    pointer.c: In function ‘main’:
    pointer.c:10:37: warning: format ‘%lu’ expects argument of type ‘long unsigned 
    int’, but argument 2 has type ‘int *’ [-Wformat=]
        10 |     printf("Address of variable = %lu\n", p);
           |                                   ~~^     ~
           |                                     |     |
           |                                     |     int *
           |                                     long unsigned int
           |                                   %ls
    pointer.c:11:39: warning: format ‘%lu’ expects argument of type ‘long unsigned 
    int’, but argument 2 has type ‘int *’ [-Wformat=]
        11 |     printf("Address of c variable = %lu\n", c);
           |                                     ~~^     ~
           |                                       |     |
           |                                       |     int *
           |                                       long unsigned int
           |                                     %ls
   Address of variable = 0x7fffc5a57474
   Address of variable = 140736509342836
   Address of c variable = 0

So, I was wondering that as to what do these compiler warnings mean, and should I be concerned about these warnings?

Also, when I used %d instead of %p or %lu, I got the values of addresses as a "negative" value, so can negative addresses exist in the memory?

Also, the address values in the output are unusually large. They are even larger than the size of my 16 GB RAM, how is that possible that my variable is stored in a location which doesn't exist?


Solution

  • You have to be careful if you're thinking about pointers as numbers. Internally, they are usually addresses, and they are usually numeric, but they are unsigned numeric. So, no, you typically won't have "negative addresses".

    You might not have learned how computers represent negative numbers. Here's a quick demonstration of the common "two's complement" representation, using only three bits. The point is that the same bit pattern can have two different interpretations, depending on whether you care about negative values or not:

    bit pattern signed int unsigned int
    000 0 0
    001 1 1
    010 2 2
    011 3 3
    100 -4 4
    101 -3 5
    110 -2 6
    111 -1 7

    So, as you can see, if you have a large, unsigned number, but you interpret it as if it's signed (like, by printing it with %d, you get a negative number, instead.

    Two other things to remember are:

    1. Pointers aren't necessarily ints. They might be — and on the currently-popular x86_64 architecture, they are — larger than ints. So trying to print them using %d is doubly wrong, and might give you a completely misleading answer.
    2. Your program often uses memory in different parts of the "address space". For example, it's common for your program's instructions, and its global variables, to be allocated in the low part of memory, starting at or near address 0. But it's common for the "stack", where local variables are typically stored, to start somewhere towards the top of the address space, and grow down. So it's common for the address of a local variable to be a very large number, seemingly bigger than the amount of memory you have in your machine. But what's actually going on is that the seemingly huge amount of memory in between isn't allocated at all, isn't "mapped in" to your address space, and so doesn't count against the amount of physical memory you have in your computer.