Variable referencing and how pointers interact with memory - c++

When a variable is created such as:
int x = 5;
it will be stored somewhere in memory, cool.
However when I change the value of the variable by doing the following:
x = 10;
What happens in memory?
Does the new value of x overwrite the old value using the same memory address?
or is it that the new value is stored in a new memory address and then the old address is deleted?
This question arose when I came across pointers. It seems that using pointers to change the value of a variable is the same as defining the variable with another value.
this is my code (most of it are comments (lol)):
#include "iostream"
int main()
{
int x = 5; // declaring and defining x to be 5
int *xPointer = &x; // declare and define xPointer as a pointer to store the reference of x
printf("%d\n",x); // print the value of x
printf("%p\n",xPointer); // print the reference of x
x = 10; //changing value of x
printf("%d\n",x); //print new value of x
printf("%p\n",xPointer); //print the reference of x to see if it changed when the value of x changed
*xPointer = 15; //changing the value of x using a pointer
printf("%d\n",x); //print new value of x
printf("%p\n",xPointer); //print reference of x to see if it changed
return 0;
}
this is the output:
5
00AFF9C0
10
00AFF9C0
15
00AFF9C0
As you can see the memory addresses are the same, hence what is the point of pointers (pun intended).

When you declare int x = 5; you are saying that x has automatic storage duration and is initialised with the value 5.
For the lifetime of x, a pointer to x (i.e. &x) will have the same value.
You can change the value of x with the assignment x = 10 or via a pointer dereference *xPointer = 15 having set int* xPointer = &x;.
The language standard mentions nothing about the pointer value being a memory address, although it might be. That's a common misconception as to how the language works.
(Indeed a new value of x might cause the location in memory to change. That's permitted by the language so long as the pointer value doesn't change. An operating system may well do something similar to this, in the interests of obviating memory defragmentation.)

Related

Trying to understand * and & in C++ [duplicate]

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 7 years ago.
I have a few questions. This isn't homework. I just want to understand better.
So if I have
int * b = &k;
Then k must be an integer, and b is a pointer to k's position in memory, correct?
What is the underlying "data type" of b? When I output it, it returns things like 0x22fe4c, which I assume is hexadecimal for memory position 2293324, correct?
Where exactly is memory position '2293324'? The "heap"? How can I output the values at, for example, memory positions 0, 1, 2, etc?
If I output *b, this is the same as outputting k directly, because * somehow means the value pointed to by b. But this seems different than the declaration of b, which was declared int * b = k, so if * means "value of" then doesn't mean this "declare b to the value of k? I know it doesn't but I still want to understand exactly what this means language wise.
If I output &b, this is actually returning the address of the pointer itself, and has nothing to do with k, correct?
I can also do int & a = k; which seems to be the same as doing int a = k;. Is it generally not necessary to use & in this way?
1- Yes.
2- There's no "underlying data type". It's a pointer to int. That's its nature. It's as data type as "int" or "char" for c/c++.
3- You shouldn't even try output values of memory which wasn't allocated by you. That's a segmentation fault. You can try by doing b-- (Which makes "b" point to the "int" before it actual position. At least, to what your program thinks it's an int.)
4- * with pointers is an operator. With any data type, it's another data type. It's like the = symbol. It has one meaning when you put == and another when you put =. The symbol doesn't necesarilly correlates with it meaning.
5- &b is the direction of b. It is related to k while b points to k. For example, if you do (**(&b)) you are making the value pointed by the value pointed by the direction of b. Which is k. If you didn't changed it, of course.
6- int & a = k means set the direction of a to the direction of k. a will be, for all means, k. If you do a=1, k will be 1. They will be both references to the same thing.
Open to corrections, of course. That's how I understand it.
In answer to your questions:
Yes, b is a pointer to k: It contains the address of k in the heap, but not the value of k itself.
The "data type" of b is an int: Essentially, this tells us that the address to which b points is the address of an int, but this has nothing to do with b itself: b is just an address to a variable.
Don't try to manually allocate memory to a specific address: Memory is allocated based of the size of the object once initialized, so memory addresses are spaced to leave room for objects to be allocated next to each other in the memory, thus manually changing this is a bad idea.
* In this case is a de-reference to b. As I've said, b is a memory address, but *b is what's at b's address. In this case, it's k, so manipulating *b is the same as manipulating k.
Correct, &b is the address of the pointer, which is distinct from both k and b itself.
Using int & a = k is creating a reference to k, which may be used as if it were k itself. This case is trivial, however, references are ideal for functions which need to alter the value of a variable which lies outside the scope of the function itself.
For instance:
void addThree(int& a) {
a += 3;
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //adds three to 'a'
a += 2; //'a' now has a value of 8
return 0;
}
In the above case, addThree takes a reference to a, meaning that the value of int a in main() is manipulated directly by the function.
This would also work with a pointer:
void addThree(int* a) { //Takes a pointer to an integer
*a += 3; //Adds 3 to the int found at the pointer's address
}
int main() {
int a = 3; //'a' has a value of 3
addThree(&a); //Passes the address of 'a' to the addThree function
a += 2; //'a' now has a value of 8
return 0;
}
But not with a copy-constructed argument:
void addThree(int a) {
a += 3; //A new variable 'a' now a has value of 6.
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //'a' still has a value of 3: The function won't change it
a += 2; //a now has a value of 5
return 0;
}
There are compliments of each other. * either declares a pointer or dereferences it. & either declares a (lvalue) reference or takes the address of an object or builtin type. So in many cases they work in tandem. To make a pointer of an object you need its address. To use a pointer as a value you dereference it.
3 - If k is a local variable, it's on the stack. If k is a static variable, it's in the data section of the program. The same applies to any variable, including b. A pointer would point to some location in the heap if new, malloc(), calloc(), ... , is used. A pointer would point to the stack if alloca() (or _alloca()) is used (alloca() is similar to using a local variable length array).
Example involving an array:
int array_of_5_integers[5];
int *ptr_to_int;
int (*ptr_to_array_of_5_integers)[5];
ptr_to_int = array_of_5_integers;
ptr_to_array_of_5_integers = &array_of_5_integers;

C++ Guidance: Understanding How Pointers Work

I found a code snippet on the internet. When I compile and run it, the output is 70. but i don't know whats happening in the code. please help me out.
#include <iostream>
using namespace std;
void doubleNumber (int *num )
{
*num = *num * 2;
}
int main ()
{
int num = 35;
doubleNumber (&num) ;
cout <<num ;
return 0;
}
void doubleNumber (int *num ) takes a pointer to an integer as parameter, which permits the method to modify the original variable.
Calling *num dereferences the pointer, while *num = *num * 2 assigns the value of the variable of the pointer num multiplied by 2 to the memory cell where num points to.
And in the main, where you have declared the integer, by calling the function doubleNumber with &num, you reference the variable and the return value of that is the pointer to the variable.
int num = 35;
doubleNumber(&num);
Is equivalent to:
int num = 35;
int* num_pointer = &num;
doubleNumber(num_pointer);
You should probably take a look at this site to read about referencing and dereferencing.
In your main function you call doubleNumber() passing a pointer to num.
The doubleNumber() function receives the pointer and doubles his value.
*num = *num * 2
The code defines a function which "doubles" an number. The main program passes the pointer to the variable num in to the function, and the function doubles the variable using the pointer passed in.
Pointers in C++ are my favorite (and - for newer programmers - are often confusing because they are learned in tandem with referencing (& operator). The * symbol is used for a lot of 'stuff' in C++, and it is not helped by the fact that, with pointers, the * symbol does two different things, for which we have two (2) names: dereferencing and indirection.
When we declare a pointer to a type, e.g. int *intPtr = //CODE HERE, we enable the variable to accept an address *intPtr and assign the address in memory of the rvalue (that on the right side of the binary operator) to the variable intPtr. intPtr - or, the address of the rvalue - can then, itself, be passed around and used as an lvalue. We call this "dereferencing".
Then, when we want to access the value of the thing stored at the memory address, we use the indirection operator * in the body of the code to access the stored value. So, let's say we do this:
int num = 35;
int num2 = 0;
int *intPtr = &num; // here using the reference operator & to assign the address
// of num to intPtr
We can then access the value stored behind num by going:
num2 = *intPtr;
Here, the * indirection operator is actually doing something else: it is used to access the value stored at the address stored in intPtr.
WHERE THE CONFUSION HAPPENS:
So, when we see a function header with a pointer as an argument, it's like "Wha'? Which * is being used?"
returntype functionIdentifier(type *num)
In this case, what is received as an argument is a memory address. Then, the argument can be used throughout the body of the function. Too, the indirection operator * can be used to access the value stored at the memory address stored in the passed-in argument (pointer - in this came num).

De-allocating memory within loops

I was reading through MIT's Introduction to C++ and one code example showed:
int *getPtrToFive() {
int *x = new int;
*x = 5;
return x;
}
int main() {
int *p;
for (int i = 0; i < 3; ++i) {
p = getPtrToFive();
cout << *p << endl;
delete p;
}
}
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new".
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new"
No. You are not deleting p, you are deleting the object p points to, which is allocated using new each iteration.
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
The value of x would be something like 0xFFd00whatever. but you are printing the value of *x, which is "the number that is in the memory at address 0xFFd00whatever". There is no x=5 in your code; there's only *x=5. It means "go to the address to which x points to, and put the number 5 in there".
You can think about it this way: you have a hand, okay? let's call it "x". The command
x = new int;
Means "point your finger at some empty place on your desk." Where
*x = 5;
Means "draw the number five where your hand points to".
p is simply a variable of the type int* (pointer to int). Its value is an address. When you assign a new value to it then it points to a new object. delete expects an address; that's all it needs to deallocate the memory you allocated.
The variable used to store said address is irrelevant. It's value has changed, and that's all delete cares about; the value.

Updating map values in c++

Newb question here:
how can I have the value stored in Maptest[2] update along with the variable?
I thought you could do it with pointers, but this doesn't work:
map<int, int*> MapTest; //create a map
int x = 7;
//this part gives an error:
//"Indirection requires pointer operand ("int" invalid)"
MapTest[2] = *x;
cout << MapTest[2]<<endl; //should print out 7...
x = 10;
cout <<MapTest[2]<<endl; //should print out 10...
What am I doing wrong?
You need the address of x. Your current code is attempting to dereference an integer.
MapTest[2] = &x;
You then need to dereference what MapTest[2] returns.
cout << *MapTest[2]<<endl;
Try this instead:
MapTest[2] = &x;
You want the address of x to store in the int*. Not the dereference of x, which would be what ever is at the memory location 0x7, which is not going to be valid.
There are at least 2 problems here:
int x = 7;
*x; // dereferences a pointer and x is not a pointer.
m[2] = x; // tries to assign an int value to a pointer-to-int value
// right
m[2] = &x; // & returns the address of a value
Now you have a new problem. x has automatic lifetime, it will be
destroyed at the end of its surrounding scope. You need to allocate it
from the free store (a.k.a. the heap).
int* x = new int(7);
m[2] = x; // works assigns pointer-to-int value to a pointer-to-int value
Now you have to remember to delete every element in the map before
it goes out of scope or you will leak memory.
It is smarter to store values in a map, or if you really need to
store pointers to store a suitable smart pointer (shared_ptr or
unique_ptr).
For the printing:
m[2]; // returns pointer value
*m[2]; // dereferences said pointer value and gives you the value that is being pointed to

Confusion about pointers and their memory addresses

alright, im looking at a code here and the idea is difficult to understand.
#include <iostream>
using namespace std;
class Point
{
public :
int X,Y;
Point() : X(0), Y(0) {}
};
void MoveUp (Point * p)
{
p -> Y += 5;
}
int main()
{
Point point;
MoveUp(&point);
cout << point.X << point.Y;
return 0;
}
Alright, so i believe that a class is created and X and Y are declared and they are put inside a constructor
a method is created and the argument is Point * p, which means that we are going to stick the constructor's pointer inside the function;
now we create an object called point then call our method and put the pointers address inside it?
isnt the pointers address just a memory number like 0x255255?
and why wasnt p ever declared?
(int * p = Y)
what is a memory addres exactly? that it can be used as an argument?
p was declared.
void MoveUp (Point * p)
{
p -> Y += 5;
}
is a function that will take a pointer to a Point and add 5 to its Y value. It's no different to the following:
void f(int n) {
printf ("%d\n", n);
}
:
int x = 7;
f(x);
You wouldn't say n wasn't defined in that case. It's the same for p in your case.
Perhaps some comments in the code would help:
#include <iostream>
using namespace std;
class Point
{
public :
int X,Y;
Point() : X(0), Y(0) {} // Constructor sets X and Y to 0.
};
void MoveUp (Point * p) // Take a Point pointer p.
{
p -> Y += 5; // Add 5 to its Y value.
}
int main()
{
Point point; // Define a Point.
MoveUp(&point); // Call MoveUp with its address.
cout <<point.X << point.Y; // Print out its values (0,5).
return 0;
}
Pointers are simply a level of indirection. In the code:
1 int X;
2 int *pX = &X;
3 X = 7;
4 *pX = 7;
the effect of lines 3 and 4 are identical. That's because pX is a pointer to X so that *pX, the contents of pX, is actually X.
In your case, p->Y is the same as (*p).Y, or the Y member of the class pointed to by p.
A pointer is simply a variable like any other but it holds a memory address.
Read that line about 6 times. The name pointer itself seems scary to people, but it is really just called this to make it easier for ourselves to think about what is happening.
The type of a pointer (for example char*, int*, Point*) simply tells the compiler what is stored at that memory address.
So all pointers are alike in that they all store a simple memory address. But they are different in that the type of the pointer will tell you what will be contained at that memory address.
and why wasnt p ever declared?
p is declared:
//p is declared to be a variable that holds an address
// and at that address it holds a type Point
//p itself only holds an address not the actual data of the Point.
void MoveUp (Point * p)
{
//The -> operator when applied to a pointer, means give me the object at
// that address and then access the following member
p->Y += 5;
}
what is a memory addres exactly? that it can be used as an argument?
You can think of a memory address simply as a number. On 32-bit programs this number is 4 bytes long. On 64-bit programs this number is 8 bytes long.
Consider the following code:
Point point;
Point *p = &point;
The point variable is of type Point. It holds an object of the class Point.
The &point expression returns an address of the Point variable point. The expression &point is of type Point*.
The p variable holds a address of type Point, the type of p is Point*. p holds the address in memory of the object point.
p is declared in the function definition
void MoveUp (Point * p)
Before you look at pointers, you have to clarify for yourself the meaning of "class", "instance" and "constructor". Your sentence
a class is created and X and Y are
declared and they are put inside a
constructor
shows the need for such clarification. Here is a discussion on books you may want to read: Books to refer for learning OOP through C++
Think about memory as contiguous small blocks.
Now, think about the Point class as something that is 2 blocks width, and you put it in any place of the memory. It doesn't matter where, the important thing is that it is placed in only ONE starting point. You can move it and change that staring point, but irrevocably will start in ONE starting point.
Then the pointer is the number of that ONE starting point.
When you pass a pointer as an argument, you doing
you: 'hey function, take this Point and do what you know!'
function: 'ok, but where is the Point!?'
you: 'oh, sorry, i don't take it with me, it's located there, in that block!'
And the function will know now that THERE is a Point, and with the magic of the compiler, the function will know that its 2 blocks width. Then the function takes it, change its Y (thanks again, compiler), and leave it where it was before (in fact, it didn't even take it away from there).
Minutes later, you go there, and see Point.Y has changed. You say 'thanks', and you go.
p was declared as a method parameter.
Pointers are a special kind of variable that hold the memory address of a value. The * symbol is the dereference symbol, which tells your code to go lookup the value IN the memory address held by the pointer. Now is also a good time to introduce the & symbol, which tells your code to get the memory address of a value. For example:
int i = 5; //int
int *pointer; //int pointer
pointer = &i; //sets pointer to the memory address of i
doMath(&i); //passes a memory address, value inside that address is being used
doMath(pointer); //same as above
dontMath(i); //value of x will be 207, value of i is still 7 since a copy is being modified
//value of pointer is a memory address
//value of *pointer is the value stored inside that memory address, 7
//value of &pointer is the memory address of pointer, which itself holds the memory address
void doMath(int *p) {
*p++;
}
void dontMath(int x){
x=x+200;
}
The confusion I had early on was the meaning of the * symbol. In variable declaration, it means that your are declaring a pointer for a certain datatype (a variable that holds a memory address). Elsewhere, it is the dereference symbol telling your code to resolve the value.