question about modifying a pointer using another pointer in a function - c++

I have a question about the following code. I am not sure why the address stored in yAdd doesn't get updated to the same address stored in the variable x inside the addfun() function in the code below? what is wrong with my thinking?
#include <iostream>
using namespace std;
void fun(int *x) {
*x = 55;
}
void addfun(int **x) {
*x = new int[3];
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
cout << &x << endl;
}
int main()
{
int y = 99;
int *yAdd = &y;
cout << y << endl;
fun(yAdd);
cout << y << endl;
cout << yAdd << endl; // original address stored in yAdd
cout << "address of y is " << &y << endl;
addfun(&yAdd); // so I update the address stored in yAdd to be the same address
// as stored inside the x in the addfun function
cout << yAdd << endl; // but how come when printing this, yAdd doesn't
// show 0x7ffc32e646a0, but something else?
return 0;
}

addfun(&yAdd);
This is passing the address of yAdd to this function, as a parameter.
yAdd is a pointer. The pointer is an address of some other object in your program. It doesn't matter what that object is, yAdd is its pointer, and whatever yAdd itself, its address gets passed.
cout << yAdd << endl;
This shows the value of yAdd. Whatever this pointer is, its value is shown. And the address of this object, of yAdd, is something completely different.
void addfun(int **x)
x is a parameter to this function. x is a variable, that has nothing to do, whatsoever, with any other variable in your program. As such, it will have its own memory address, different than the memory address of everything else in your program (at least while it exists).
cout << &x << endl;
And this shows x's address. It is not showing the value of yAdd. It is not showing yAdds address, either. It is showing the address of x, a parameter to this function.
All of these are separate, distinct, objects and values in your program.

I changed the code to print out some more and label it better:
#include <iostream>
using namespace std;
void fun(int *x) {
*x = 55;
}
void addfun(int **x) {
cout << endl << "addfun()" << endl;
cout << "x = " << x << endl;
cout << "*x = " << *x << endl;
cout << "new int[3]" << endl;
*x = new int[3];
cout << "x = " << x << endl;
cout << "*x = " << *x << endl;
cout << "addfun() done" << endl << endl;
}
int main()
{
int y = 99;
int *yAdd = &y;
cout << y << endl;
fun(yAdd);
cout << y << endl;
cout << "&yAdd = " << &yAdd << endl;
cout << "yAdd = " << yAdd << endl;
cout << "*yAdd = " << *yAdd << endl;
cout << "address of y is " << &y << endl;
addfun(&yAdd); // so I update the address stored in yAdd to be the same address
// as stored inside the x in the addfun function
cout << "&yAdd = " << &yAdd << endl;
cout << "yAdd = " << yAdd << endl;
cout << "*yAdd = " << *yAdd << endl;
return 0;
}
This produces for example the following output:
99
55
&yAdd = 0x7ffc9e47fe58
yAdd = 0x7ffc9e47fe54
*yAdd = 55
address of y is 0x7ffc9e47fe54
addfun()
x = 0x7ffc9e47fe58
*x = 0x7ffc9e47fe54
new int[3]
x = 0x7ffc9e47fe58
*x = 0x564ab462d2c0
addfun() done
&yAdd = 0x7ffc9e47fe58
yAdd = 0x564ab462d2c0
*yAdd = 0
As you can see when you enter addfun the value of x is the address of yAdd which points to y. Then you allocate the int[3] and assign the result to *x. That is you store the address of int[3] into where x points to, namely yAdd. The value of x is not changed.
After the call to addfun you can see that the address of yAdd is still the same as and the same as x was but where yAdd points to has now been changed to int[3].
I think the bit where you got confused is *x = .... That changes the things x points at and not x itself.

Within the function addfun
void addfun(int **x) {
*x = new int[3];
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
cout << &x << endl;
}
the statement
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
prints the address of the original pointer yAdd passed to the function
addfun(&yAdd);
In main this statement
cout << yAdd << endl;
outputs the value assigned to the pointer within the function addfun in this statement
*x = new int[3];
that is the address of the dynamically allocated memory.
The assigned value to the pointer yAdd and the address of the pointer itself are two different values.

Related

Understanding Delete in c++ [duplicate]

This question already has answers here:
Using pointer after free()
(6 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 months ago.
I created a pointer code in which I played with pointers a little bit but when I tried to delete my pointer variable it still showed me the value which was stored in a pointer variable, after deletion I can still be able to use that pointer variable but I deleted that pointer variable so how can I reuse that after deleting? I don't get that.
Code:
#include<iostream>
int main()
{
using namespace std;
int *m = new int;
int *ab = new int;
cout << "Enter value of m: ";
cin >> *m;
cout << "Address of pointer m: " << m <<endl;
cout << "Content of pointer m: " << *m << endl;
ab = m;
cout << "Address of pointer ab: " << ab <<endl;
cout << "Content of pointer ab: " << *ab << endl;
*m = 34;
cout << "Address of pointer ab: " << ab <<endl;
cout << "Content of pointer ab: " << *ab << endl;
*ab = 7;
cout << "Address of pointer m: " << m <<endl;
cout << "Content of pointer m: " << *m << endl;
delete ab;
delete m;
cout << *m + 1 << endl; //this is giving me result of *m + 1 which is not ok cuz I deleted pointer variable on above line.
return 0;
}

What happens when I use *(int*)&x to assign to a constant value x? [duplicate]

This question already has answers here:
Modifying a const int in C++ [duplicate]
(2 answers)
Closed 5 years ago.
I have tried the following codes:
#include <iostream>
using namespace std;
struct MyClass {
const int x;
};
int main() {
MyClass c = {3};
const int *p = &c.x;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << endl;
*(int*)&c.x = 4;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << (p == &c.x) << endl;
cout << (*p == *(&c.x)) << endl;
return 0;
}
Then I get the following answer:
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 4
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 4
1
1
It seems that I have successfully change the value of constant integer x. But when I directly declare x in main() instead of in a class, I get the totally different answer.
#include <iostream>
using namespace std;
int main() {
const int x = 3;
const int *p = &x;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
*(int*)&x = 4;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
cout << (p == &x) << endl;
cout << (*p == *(&x)) << endl;
return 0;
}
The result is
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 3
1
0
That is really strange that (p == &x) is true but (*p == *(&x)) is false!!! I don't know what's going on in the second codes.
What you're doing is undefined behaviour, so anything can happen. The C++ standard says:
Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.8) results in undefined behavior.
And:
[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier may produce undefined
behavior (10.1.7.1). — end note]
So you can cast away the "const" to get int* but attempting to actually modify the variable through that pointer is undefined.
The reason you can cast away the const is that it might not actually point to a constant:
int i = 0;
const int* p = &i;
*(int*)p = 1; // OK, because p points to a non-constant
const int j = 0;
const int* q = &j;
*(int*)q = 1; // NOT OK, because q points to a constant
In your second example the compiler is making assumptions when optimizing, based on the fact it knows that a constant value will not change, so it doesn't bother testing its value. The assumption is correct because a correct program can never change the value of a constant. Your program is not correct, but that means the compiler isn't required to give a sensible result.

Referencing a Double Pointer, what is the value?

I cant figure out why the output of this program is what it is. Maybe some one can help me out.
And why does the reference of double Pointer: 0062FB78?
Why does the reference of dereferenced double pointer = 0062FAA0?
Should'nt these be flipped?
0062FB78 is the address of x
I am guess 0062FAA0 is the address of the double Pointer?
#include <iostream>
void print(int x) {
std::cout << "value: " << (x) << "\n";
std::cout << "reference: " << (&x) << "\n";
//std::cout << (*x) << "\n";
}
void printPointer(int *x) {
std::cout << "value: " << x << "\n";
std::cout << "reference: " << &x << "\n";
std::cout << "dereference:" << *x << "\n";
}
void printDoublePointer(int **x) {
std::cout << "value: " << x << "\n";
std::cout << "reference: " << &x << "\n";
std::cout << "dereference:" << *x << "\n";
printPointer(*x);
}
void printTripplePointer(int ***x) {
std::cout << "value:" << x << "\n";
std::cout << "reference:" << &x << "\n";
std::cout << "dereference:" << *x << "\n";
printDoublePointer(*x);
}
void print(char* string) {
std::cout << "\n" << string << "\n";
}
int main()
{
int x = 19;
int *y; // y is a address space
y = &x; // &y now points to the address of x, *y now has the value of x
int **doublePointer = &y;
print(x);
printPointer(y);
printDoublePointer(doublePointer);
print("doublePointer");
std::cin >> x;
}
x
value: 19
reference: 0062FBB78
y
value: 0062FC7C
reference: 0062FBB78
defererence: 19
doublePointer
value: 0062FC58
reference of double Pointer: 0062FB78
dereference of doble Pointer: 0062FC7C
value of dereferenced double pointer: 0062FC7C
reference of dereferenced double pointer: 0062FAA0
dereference: 19
Before going over you problem, let's first agree that after calling y= &x, y is not a reference to x, but rather the address of x.
Now, let's examine the call to print
If you pay close attention, we pass the variable by-value, so this method will actually print the value 19, but the address will belong to a temp copy of x.
If we would have changed the prototype to the following one, the address of x printed here will be equal to the address of y printed in the method printPointer
void print(int & x) {
std::cout << __PRETTY_FUNCTION__ << "\n";
std::cout << "value: " << (x) << "\n";
std::cout << "reference: " << (&x) << "\n";
}
Regarding your other concern, these too occur because you pass the pointers by-value and not by-reference.
This simple program shows that everything works just fine:
int main()
{
int x = 19;
int *y = &x;
int **z = &y;
std::cout << x << "\t" << &x << std::endl;
std::cout << y << "\t" << &y << "\t" << *y << std::endl;
std::cout << z << "\t" << &z << "\t" << *z << std::endl;
}

Redefining a corrupted reference

class A
{
};
int main()
{
A *a= new A(); // variable "a" must be pointer, I can't edit this line
A& b = *a; //b must be a reference
delete a; //deletion
a= new A(); //re-definition
//b is now corrupted.
}
In a piece of code that I have to work with, a pointer to an object of class A is created and a reference to this pointer too.
For some reasons, I have to delete the pointer and re-defined it. How can I get b to work again ?
You can do this, subject to some constraints:
A* a = new A(); // variable "a" must be pointer, I can't edit this line
A& b = *a; // b must be a reference
a->~A(); // destroy first object
new (a) A(); // create second, new object in its place
delete a; // destroy second object and release memory
The constraints are if A contains non-static const data members, you cannot use b after the reconstruction.
(Starting with C++17, you can reuse a reconstructed object even if it has const members by using some extra acrobatics: A& b2 = *std::launder(a); But you still cannot reuse b as is.)
in your code you are not using a reference to a pointer, to do so:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int* ptrA = new int(77);
int*& rPtrA = ptrA; // this a reference to a pointer
cout << "ptrA: " << ptrA << endl;
cout << "*ptrA: " << *ptrA << endl;
cout << "rPtrA: " << rPtrA << endl;
cout << "*rPtrA: " << *rPtrA << endl;
delete ptrA;
ptrA = NULL;
cout << "ptrA: " << ptrA << endl;
// cout << "*ptrA: " << *ptrA << endl; // cause runtme error
cout << "rPtrA: " << rPtrA << endl;
// cout << "*rPtrA: " << *rPtrA << endl;// cause runtme error
ptrA = new int(100);
cout << "ptrA: " << ptrA << endl;
cout << "*ptrA: " << *ptrA << endl;
cout << "rPtrA: " << rPtrA << endl;
cout << "*rPtrA: " << *rPtrA << endl;
delete rPtrA; // delete pointer through its reference
rPtrA = NULL;
cout << "ptrA: " << ptrA << endl;
// cout << "*ptrA: " << *ptrA << endl; // runtime error
cout << "rPtrA: " << rPtrA << endl;
// cout << "*rPtrA: " << *rPtrA << endl; // runtime error
return 0;
}
&* is used for reference to pointer not just &.
a reference is a just another pseudonym to a variable so whatever the variable changes the reference changes also.
a reference to a pointer REFERS to the POINTER'S ADDRESS not the address the pointer stores (value of pointer).
in your code you used a reference to the value(what pointer stores not the pointer itself) the pointer points to

Pointer of int type moves 1 address in memory after incrementing it

The code works as expected until the lines 22-24, where we are printing 8 followed by address. Incrementing the pointer address increments the address by one byte only, whereas it should move address by 4 bytes. The problem does not occur in arrays or if lines 22-24 are run separately.
#include<iostream>
using namespace std;
void main()
{
int *p;
//int a[10] = { 0 };
//p = a;
int a = 100;
p=&a;
cout << "1. "<<p <<" "<<*p<< endl;
p++;
cout << "2. " << p << " " << *p << endl;
++p;
cout << "3. " << p << " " << *p << endl;
++*p;
cout << "4. " << p << " " << *p << endl;
++(*p);
cout << "5. " << p << " " << *p << endl;
++*(p);
cout << "6. " << p << " " << *p << endl;
*p++;
cout << "7. " << p << " " << *p << endl;
(*p)++; //This is the problem, increments the address by 1, even though its in int type
cout << "8. " << p << " " << *p << endl;
*(p)++;
cout << "9. " << p << " " << *p << endl;
*++p;
cout << "10. " << p << " " << *p << endl;
*(++p);
cout << "11. " << p << " " << *p << endl;
cin.get();
}
Initially you set p to point to an integer variable on the stack. When you subsequently increment the pointer you are pointing to an area of memory on the stack which is likely to change when a function is called ( cout for example). when the function returns it will probably have changed the memory location that your incremented pointer p is pointing to and this probably explains your issue.
You should declare an array large enough to accommodate the range of pointer addresses that you are going to step through. I notice that you commented out the array code which would have worked as you expected.
Your code is:
p = &a;
p++;
Now p is pointing past the end of a. This is still OK, however on the next line:
cout << "2. " << p << " " << *p << endl;
when you write *p this tries to read the memory past the end of a, which causes undefined behaviour.
When undefined behaviour has happened, the definition of the C++ language no longer covers what the program does. Anything can happen.
To put it another way: when generating the executable, the compiler can make assumptions based on the premise that your program only does things which are well-defined.
Your output could perhaps be explained by the compiler making such an assumption which would be justified if your program were confirming, but is actually false because your program is invalid.
One explanation that comes to mind is that you advanced p until it happens to be pointing to the memory location in which p itself is stored. The compiler implements (*p)++ by outputting an instruction for incrementing an int stored at the location where p is pointing. On your system, the result of applying this instruction to the location where actually p is stored is to increase the address value of p by one.