Assigning values to a pointer

13,337

Solution 1

In your example this is a compiler error.

However what I assume you wanted to do was this:

int n =23, *p;
p = &n;
//Change the value of p to 3000, p now points to address 3000
p = reinterpret_cast<int*>(3000); 
//Check if the address of n has changed
std::cout << "Address of n : " << reinterpret_cast<int>(&n) << std::endl; 

As you can tell when you run this code. The address of n does not change.

For your second question.

Yes and No :)

If you define two variables next to each other they may be next to each other in memory.

 int a,b,c,d;
 char c = 1;
 short s = 1;
 void* p = nullptr;
 int i = 1;

 std::cout << "a is at: " << reinterpret_cast<int>(&a) << std::endl;
 std::cout << "b is at: " << reinterpret_cast<int>(&b) << std::endl;
 std::cout << "c is at: " << reinterpret_cast<int>(&c) << std::endl;
 std::cout << "d is at: " << reinterpret_cast<int>(&d) << std::endl;
 std::cout << "Char is at: " << reinterpret_cast<int>(&c) << std::endl;
 std::cout << "Short is at: " << reinterpret_cast<int>(&s) << std::endl;
 std::cout << "Pointer is at: " << reinterpret_cast<int>(p) << std::endl;
 std::cout << "Int is at: " << reinterpret_cast<int>(&i) << std::endl;

This behavior is caused the compiler determining where to stick everthting. It may or may not exist next to each other. If you want to guarantee they exist next to one another, use an array.

int arr[] = {1,2,3,4,5,6,7};
int * p = &arr[0]; //get address of first element
for(int i = 0 ; i < 7; ++i)
    std::cout << "Value at address: " << reinterpret_cast<int>(p+i) 
        << " is: " << *( p + i) << std::endl;

Solution 2

You can cast an int to a pointer. It is standard. And standard guarantees that if you cast the pointer back to an int you should get the original value, provided no truncation occured in between.

But dereferencing such a pointer is Undefined Behaviour. That means that in common implementation, you will either get a segment fault or memory violation if you try to read an unmapped or writeonly address, or simply get an unpredictible value because you read at a location that you do not know what lies there...

And it is even worse if you write there, because you could overwrite random location in your program. Just imagine what can happen when you overwrite the return address from a function...

The only real use case for that, is when some special hardware registers are mapped at well known addresses. Then you actually write:

char *p;
p = 0x60;    // say 0x60 is the address of a special register you want to read
char reg_value = *p;

This cannot be defined by standard, because the standard makes no assumption on the underlying platform, but is then a local extension that should be documented for a particular hardware platform.

Solution 3

Assuming you make it compile by adding a cast

p=(int *)5;

Then dereferencing that pointer will be undefined behavior. It can do anything but most likely your program will abort. It can behave differently on different systems.

Also, what address a variable or the next gets is also dependant on the system you run your program on. Most systems use a stack for local variables, but they can count up or down so you dont know.

Debug and optimize builds can emit different code too. Some compilers leave space after local arrays or variables so they can give a meaningful error when you write outside the array. But in release they might use memory as tight as possible.

To make matters even more unpredictable, the main stream operating systems have a technique called address space layout randomization (ASLR).

https://en.wikipedia.org/wiki/Address_space_layout_randomization

The base address that variables get will be randomized every time the program is run. this way hackers can't abuse buffer overflows and calculate return addresses anymore where they inject their own code.

So no you cant say anything general about variable addresses. You have to check with your compiler and operating system.

Solution 4

Lets use an analogy....

int  x = 3;
int* x_p = &x;

You can see it like that: You now have one piece of paper, called x which has the number 3 written on it. And you have another piece of paper that has the location of the first piece of paper written on it. How this is done in detail actually does not matter, so lets say the second piece of paper is called x_p and has a x written on it. In this terms,

int y = *x_p;

means: look at paper x_p, interpret this as the location of another piece of paper and take the value written on that one, i.e. y will have the value 3.

Now, what happens if you write something else on the paper x_p? First of all, if you still try to interpret it as the location of another piece of paper, you will fail, or you will just get a random piece of paper, but not the one you were looking for. Second, how does this effect the first piece of paper x? It does not affect it at all. Pointers are just variables like any others, just that you usually interpret their value as the location of some other variable, but otherwise there is no connection between the pointer and the pointee.

Not the best analogy, but maybe it helps.

Share:
13,337
Anchith Acharya
Author by

Anchith Acharya

Updated on July 07, 2022

Comments

  • Anchith Acharya
    Anchith Acharya almost 2 years

    I have a bit of trouble understanding the concept of pointers, and one of them is this:
    Let us declare an integer type variable n, and a pointer to it *p.
    int n=23,*p;
    Now,
    p=&n;, if I am not wrong, assigns the address of variable n (say, 3000) to p.
    So cout<<p<<" "<<*p; would output 3000 and 23 respectively.
    My doubt here is that suppose we did something like this:
    p=5; i.e. assigning a numerical value to a variable designed to hold memory locations, what would happen?
    Is the variable moved to the memory location '5' (most likely not) or is the pointer just converted to an 'int' and made to hold the value 5? I would have tried this out myself, only messing with my system's memory made me have second thoughts.

    Also, when we declare any variable (suppose int with 2 bytes space), is it stored in a random memory location like 3000, 101, 2700 or something, or is it stored in 0,2,4,etc.? And is the next variable declared stored right in the next one (like 3002, 103 or 2702), or is there some kind of gap in-between?