Declare a pointer with assigned value

Viewed 137
#include <stdio.h>

int main()
{
    int *p = 65; 
    printf("%d\n", *p);
    return 0;
}

This throws segmentation fault.

But this:

int main()
{
    int *p = 65; 
    printf("%d\n", p);
    return 0;
}

Prints the value.

Can anyone help in understanding this?

What happens when we declare pointer variables with values? (Ex: int *x = 'A';)

5 Answers

A pointer, like any other variable, can hold a value, whitch should be a memory address, but you can assign to it whatever value you'd like, so int *p = 65 (or int *x = 'A') is valid.

You can also print this value by using printf("%d\n", p), though the specifier is wrong, it should be %p.

However when you dereference it, i.e. printf("%d\n", *p) you will try to print the value stored in the address stored in the pointer, in this case the address would be 65. That is a lottery, it maybe the case that by sheer luck the value you assigned is indeed a valid memory address, and in that case the program will work correctly and print whatever value is stored in the address, otherwise the program exhibits undefined behavior, for which one of the possible outcomes is a segmentation fault.

The first one dereferences p and tries to print it. Issue is that you don't know whether 65 is a valid address to read from/dereference, and neither does the compiler. Apparently in your case, it isn't, so segfault.

The second program prints the address 65. The correct format specifier for this is %p however, and if your pointer size is 8 bytes, the address might even get truncated in other cases. Nonetheless, it prints the address 65. Apart from the format specifier being wrong, this is well-defined because it doesn't actually try to dereference the pointer, it just prints the address it is pointing to.

   65   66     67    68    69    70    71   72    73
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  a  |  b  |  c  |  d  |     |     |     |     |     |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+

Imagine this is a memory print, and the numbers are their respective addresses. If I ask you "what is at address 68?", you would reply "The letter d". Likewise, if I asked "what is at address 70?", you'd say "Nothing".

When you use pointers, this is basically what you are doing: asking the computer what are the contents of an address.

int *p;  // now you can ask the computer for address
p = 65;  // hey, computer, I'm gonna ask about the address 65
printf("%c", *p); // the computer access the address, then answers.

In the above example, the computer would tell you (via printf), that "the contents at address 65, which you asked me, is the letter a". From this you can see that a pointer is a "two-way" variable. You set the address it should look for when you dereference it (use the *p).

int *p;
p = 65;

// is equivalent to
int *p = 65

In the above example, you are telling the computer you are interested in the address 65. And when you dereference the pointer, you are asking the computer "what is the contents of this address you have?". When you do this, the computer tries to access that memory address. If you do not have permissions or if the address is invalid, you get a segmentation fault. (By the standard, it's undefined behavior...)

int *p;  // now you can ask the computer for address
p = 70;  // hey, computer, I'm gonna ask about the address 70
printf("%d", *p); // the computer access the address, then answers.

And in the above example, the computer would reply with "there is nothing at that address".

int *p = 65;

is not assigning the value 65 to some int object that p points to; it is treating the value 65 as the address of another int object; this almost certainly not a valid address, which is why you get the segfault when you try to dereference it with *p.

When you just print the value stored in p itself you're not attempting to dereference anything, which is why it works (although you're using the wrong conversion specifier - use %p to print pointer values).

The reason of SEGFAULT is explained in other answers. However, if you want to create an "initialized" pointer that points to int of value 42 you can use a compound literal.

int *p = &(int){42};

It's equivalent of:

int some_int = 42;
int *p = &some_int;
Related