3

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?.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
B_San
  • 108
  • 12
  • 1
    With `int *ptr = ....` you are declaring a pointer to integer, initializing it with something that is not a real address. It is ptr that will be equal to 0xc42, not *ptr! Later you access that address, and it is illegal because the address IS illegal. – Roberto Caboni Mar 19 '20 at 07:17
  • @RobertoCaboni thanks for reply. So, does int *ptr = &a in case 2 creates the object and that later can be changed to different integer values, as in case 2?. But in case-1 that is missing? Is my understanding is right!!? how does case 1 assignment leads to illegal is what I am trying understand, please correct me if I am wrong. – B_San Mar 19 '20 at 07:23

3 Answers3

4

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.
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
3

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.

  • thanks for your reply, I am basically interested to know, though we assume 0xc989 has the valid content will that make next assignment of *ptr = 45; make legal? If not what is difference between case-1 and case-2 then? – B_San Mar 19 '20 at 07:17
  • 1
    @B_San if it is not read only as well, you can read/write to. – Soner from The Ottoman Empire Mar 19 '20 at 07:18
  • 1
    @B_san see my comment. – Roberto Caboni Mar 19 '20 at 07:18
  • 1
    It isn't perfectly valid, it is not valid C. https://stackoverflow.com/questions/52186834/pointer-from-integer-integer-from-pointer-without-a-cast-issues – Lundin Mar 19 '20 at 07:20
  • 2
    @Lundin It is correct, but not the real core of OP's mistake. They think that with `int *ptr= 42;` they are deferencing the pointer just for that contiguous `*ptr`. – Roberto Caboni Mar 19 '20 at 07:24
  • @Lundin thanks for the link, it gave me some insight about the valid purpose of integer pointers. +1 – B_San Mar 19 '20 at 07:30
3

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396