In the following code, I am having trouble figuring out how to make b point to c so that if you change the value pointed to by b, c is changed (but not a). I tried int *b = &c;. So my question ultimately is: How do you point to a value that is pointing to another, without changing the value of the former?
#include <iostream>
int main(){
int a = 8;
int c = 12;
//std::cout<< a<< std::endl;
std::cout << &a << std::endl;
int *b = &a;
std::cout << *b << std::endl;
std::cout << b << std::endl;
std::cout << b+1 << std::endl;
a = 6;
std::cout << *b << std::endl;
b = &c; // just edited this now it works.
//std::cout << c << std::endl;
system("pause");
return 0;
}
Just take the address of c and assign it to b:
b = &c;
Now if you dereference b, with *b, you get the object denoted by c. If you modify this object in anyway, it will not affect the value of a.
Related
I am new in coding Please explain this code. I didn't get this logic.
#include<iostream>
void main()
{
int a = 32, *p = &a;
char c ='A', &ch = c;
ch += a;
*p += c;
cout << "\n" << a << " " << c << endl;
}
Since p is the location of a, *p – the int at that location – is the same int as a.
Similarly, since ch is a reference to c, ch is the same char as c.
Thus, what you have is equivalent to (after fixing the typos)
#include<iostream>
int main()
{
int a = 32;
char c ='A';
c += a;
a += c;
std::cout << "\n" << a << " " << c << std::endl;
}
How pointers are compared in C++?
The last line in the following code shows that values of b and c are different. However, b==c returns true.
#include <iostream>
struct A { int a; };
struct B { int b; };
struct C : A, B { };
int main() {
auto c = new C();
B* b = static_cast<B*>(c);
A* a = static_cast<A*>(c);
a->a = 1;
b->b = 2;
std::cout << c->a << c->b <<"\n";
std::cout << (a==c) << (b==c) << "\n";
std::cout << (long)a << "\n" << (long)b << "\n" << (long)c <<"\n";
}
A sample output that I received using GCC and Clang:
12
11
34073632
34073636
34073632
Don't cast pointers to long, cast them to intptr_t.
std::cout << (intptr_t)a << "\n" << (intptr_t)b << "\n" << (intptr_t)c <<"\n";
Anyhow, see this definition:
struct C : A, B { };
in memory that would look like:
{
A; [sizeof int]
B; [sizeof int]
}
Since A and B are both base classes of C, when you do this:
A* a = static_cast<A*>(c);
You get a pointer to the first 4 bytes of C. When you do this:
B* b = static_cast<B*>(c);
You get a pointer to the last 4 bytes of C, hence the difference. A pointer to type C will always implicitly cast the pointer this way.
I am having some doubts about the following code:
void b(int** a){
int *c = new int;
*a = c;
**a = 120;
}
int main(){
int *a = nullptr;
b(&a);
if(a)
delete a;
return 0;
}
My concern is that could cause UB, as it is a nullptr and I am changing the pointer address as I am getting an reference to it, but then I started to think that this should not be an issue as I will have.
Some address -> nullptr. And this some address is valid so I can change it.
I ran this test more than once and with the -fsanitize=address enabled and it works fine.
But, is this correct?
My concern is that could cause UB, as it is a nullptr
The a that is the argument of b() is not nullptr, and it will assign the pointed pointer before dereferencing it, so this is not a concern.
I don't think you have a memory leak, but you have to be VERY careful with things like this:
#include <iostream>
void b(int** a)
{
int *c = new int;
*a = c;
**a = 120;
// if C is deleted then the *a needs to be set to nullptr
//delete c;
//*a = nullptr;
// Not needed as this will just be defeferenced off the stack
// *a and c are two different pointers in memory so this is fine
c = nullptr;
}
int main(){
int *a = nullptr;
std::cout << "Before B, a=" << a << std::endl;
b(&a);
std::cout << "After B, a=" << a << std::endl;
std::cout << "After B, *a=" << *a << std::endl;
if(a)
{
delete a;
}
// a still has a pointer with an address and can't be trusted
std::cout << "End A, a=" << a << std::endl;
// On repl.it, it prints 0
std::cout << "End *a, a=" << *a << std::endl;
return 0;
}
I have the simple program:
#include <iostream>
using namespace std;
int main()
{
int a = 5;
int b = 6;
int* p1 = &a;
int* p2 = &b;
std::cout << p1 << " " << p2 << " ,sizeof(int)=" << sizeof(int) << std::endl;
system("pause");
return 0;
}
It produces the following output:
00DBF9B8 00DBF9AC ,sizeof(int)=4
but, 00DBF9B8 - 00DBF9AC == С. I cannot understand this result.
If I modify the program like this:
#include <iostream>
using namespace std;
int main()
{
static int a = 5;
static int b = 6;
int* p1 = &a;
int* p2 = &b;
std::cout << p1 << " " << p2 << " ,sizeof(int)=" << sizeof(int) << std::endl;
system("pause");
return 0;
}
I got correct result:
00394000 00394004 ,sizeof(int)=4
There is no guarantee that local variables (or even static variables) are put on consecutive memory addresses. And actually it would be undefined behaviour if you substracted two pointer values that do not point into the same array.
But you could use pointer arithmetics as follows:
int main()
{
int a;
int* p1 = &a;
int* p2 = p1+1;
std::cout << p1 << " " << p2 << " ,sizeof(int)=" << sizeof(int) << std::endl;
return 0;
}
Note that a single integral value may be considered as an array of size 1, and that p1+1 therefore points to "one after the last element of an array", such that the operation p2 = p1+1 is actually valid (dereferencing p2 then would not be valid, of course).
I wonder how pointers are compared when it comes to multiple inheritance. It seems that in some circumstance, they are equal although the address is obviously different. See the following code:
class A {
int m_i;
};
class B {
double m_d;
};
class C: public A, public B {
char m_c;
};
int main() {
C c;
A *pa = &c;
B *pb = &c;
std::cout << "Address of c is: " << &c << std::endl;
std::cout << "A type pointer to c is: " << pa << std::endl;
std::cout << "B type pointer to c is: " << pb << std::endl;
std::cout << "if pa == &c: " << (pa == &c) << std::endl;
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
return 0;
}
The output is:
Address of c is: 00F6F870
A type pointer to c is: 00F6F870
B type pointer to c is: 00F6F878
if pa == &c: 1
if pb == &c: 1
There is no wonder pb is different from &c. The weird thing is (pb == &c) delivers 1. I am now confused how (pb == &c) is actually evaluated.
You can only compare values that have the same type. Note, I'm ignoring the case of an overloaded operator== for the purpose of this answer.
Here, you're comparing two pointers to different classes. At this point, the compiler tries to figure out if it's possible to convert one of the pointers to the type of the other pointer.
A pointer to a subclass can be automatically converted to a pointer to its superclass. And this is what the compiler does. The end result is the same actual pointer value, and they compare equal.
This line:
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
in order to compare &c with pb it has to perform a conversion so that the types of the two values match. We already know that (B*)&c results in the value that is in pb, so what actually happens here is quite simply
std::cout << "if pb == &c: " << (pb == (B*)&c) << std::endl;
which results in comparing equal values.
class X {
char m_x;
};
class A {
int m_i;
};
class B {
double m_d;
};
class C: public X, public A, public B {
char m_c;
};
int main() {
C c;
A *pa = &c;
B *pb = &c;
void *va = pa;
void *vb = pb;
std::cout << "Address of c is: " << &c << std::endl;
std::cout << "A type pointer to c is: " << pa << std::endl;
std::cout << "B type pointer to c is: " << pb << std::endl;
std::cout << "void type pointer equal to pA is: " << va << std::endl;
std::cout << "void type pointer equal to pB is: " << vb << std::endl;
std::cout << "if pa == &c: " << (pa == &c) << std::endl;
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
std::cout << "if va == &c: " << (&c == va) << std::endl;
std::cout << "if vb == &c: " << (&c == vb) << std::endl;
return 0;
}
yields the following result:
Address of c is: 0x75270a47f5f0
A type pointer to c is: 0x75270a47f5f4
B type pointer to c is: 0x75270a47f5f8
void type pointer equal to pA is: 0x75270a47f5f4
void type pointer equal to pB is: 0x75270a47f5f8
if pa == &c: 1
if pb == &c: 1
if va == &c: 0
if vb == &c: 0
The compiler converts the &c address by casting it to the same type as the pointer you compared it to. To make the point clear I displaced Class A using another class, when I then copy the addresses to void* pointers it becomes clear that the actual 'value' stored is not equal to the 'value' stored in &c.