How does the int *ptr= 5; is different than that of int *ptr= address of variable?

Viewed 1275

Though it is very basic and might seem silly, I am trying to understand what is difference between the int *ptr = 45 or 0xc8750; (some number) vs. int *ptr= &a; (address of variable).

What I already know is:

  • Pointers are made to store address of variables and to modify contents of pointed variables ( but I want to know how it will be achieved)
  • In latter case, I can assign *ptr to different address that is legal.
  • But, in first case it is illegal!.

Why the latter is illegal if both address/number are integers? How differently will they be treated while storing in memory?

I have two piece of code/programs basically to highlight the same:

case-1:

#include <stdio.h>

int main()
{    
    int *ptr = 0xc42; // is this stored in read only memory?!! which later leads to seg faults in further assignments?!
    *ptr = 45; //illegal leads seg fault.
    return 0;
}

case-2:

int main()
{
    int a=10, b=20;
    int *ptr = &a;  // is here get any special treatment and object will be created for *ptr!!!
    *ptr = &b; //legal
    printf(" *ptr = %d \n", *ptr);
    *ptr = 20; //legal !!
    printf(" *ptr = %d \n", *ptr);
    *ptr = 50; //legal
    printf(" *ptr = %d \n", *ptr);
    return 0;
}

As we can see the *ptr = 20 and *ptr = 50 are legal and fine! (No segmentation faults).

Why is this assignment of int *ptr = 0xc989 or 5 different from int *ptr = &variable?.

3 Answers

Let's start from basics: a pointer is a variable containing the address pointing to data of a given type. If we declare

datatype* foo;

foo (that is currently not initialized) will contain the address of a variable of type datatype, and deferencing it

*foo = ...;

we are accessing that address and storing there its value.


In both cases we have * foo, but they're not the same!

  • In the first case the asterisk refers to datatype. The variable type is datatype *; the variable name is foo. foo contains an address.
  • In the second case we are dereferencing the address, in order to access it. The asterisk refers to the variable in order to perform the pointer dereferentiation.

So, when you write

int *ptr = 0xc42; // is this stored in read only memory?!!
                  // which later leads to seg faults in further assignments?!
*ptr = 45; //illegal leads seg fault.
  • With int *ptr = 0xc42; you are saying to the compiler that you are declaring a variable named ptr, of type int * and whose first value is 0xC42. (Note: as correctly stated by user Lundin, this assignment requires a further cast in order to be valid C).
  • With *ptr = 45; you are accessing the address pointed by ptr and assigning value 45. Is it legal? Well, it is if you previously assigned a valid address (and generally speaking it is if you assign to a pointer another variable's address with & operator, e.g int *ptr = &a;). But if you assign a random integer to it... it will likely lead to a segmentation fault.

Logically, if you are sure that the location, 0xc989, preserves what you need, int *ptr = 0xc989 perfectly valid (with regard to your thinking concept, as said by Roberto Caboni).

Technically, as said by Lundin, you need to cast it according to C standards.

First of all int *ptr = 0xc42; is not valid C and will not compile cleanly on a compiler configured to strict standard C. With gcc, clang and icc this means compiling with -std=c11 -pedantic-errors. For details, see "Pointer from integer/integer from pointer without a cast" issues.

int *ptr = (int*)0xc42; is valid C but fishy. To clarify, this stores an address inside the pointer variable itself, it doesn't store a value. So if you know that there is an int-sized item at memory address 0xc42, such as a memory-mapped hardware register, then you can point directly do it. But when doing so, it will only be meaningful to do that using volatile: volatile int *ptr = (volatile int*)0xc42;. Code like that mostly makes sense in embedded systems and other hardware-related programming.

As for why your second example works fine, the addresses there are assigned by the linker and not by the programmer, so they will point at valid, allocated data.

Related