Why is the pointer declared in main() not changed? [duplicate] - c++

This question already has answers here:
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 4 years ago.
I know call by pointers in which we pass address of variables.Something like this:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);
And also call by reference,in both of these methods the changes made in the function are reflected in actual arguments' variable.
But why are actual parameters passed in this case of call not changed:
#include <iostream>
using namespace std;
void foo(int* c){
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout<<&c<<endl; //0x7ffe1a74f3b0
foo(c);
cout<<*c<<endl;//5
cout<<&c<<endl;//0x7ffe1a74f3b0
}
Here c passed to foo() is address of a.So how this is call by value.
Here c should have printed garbage value according to me.Please explain what has happened here.

And also call by reference, in both of these methods the changes made in the function are reflected in actual arguments' variable.
There is an important difference, though: the changes are always made to whatever is referenced/pointed to, never to the reference/pointer itself (modifying a reference is impossible in general).
That is why assigning c a new value inside foo has no effect on c outside foo: the pointer passed to a function is copied.
If you need to modify the pointer, you need to add another level of dereference by passing a pointer reference or a pointer to a pointer.

Following on from comments, the variable c defined in function main is a different variable to the parameter c of function foo. If you want foo to be able to modify main's c, that is modify the address that c's pointer type holds, then you need to pass either a reference or pointer to c to the function instead.
Here is an example that shows the difference between passing c by value (as int *), or by reference (as int ** or int *&). Don't be fooled by the fact that int * is a pointer type, that means that it can receive an int by reference or an int * by value. And since main's c is int * rather than int, main c is being passed by value.
Note the differences in how the functions are called (whether c needs the address operator & in the function call) and the outcome of each function.
#include <iostream>
using namespace std;
void foo_int_ptr(int* c)
{
c=c+1;
}
void foo_int_ptr_ptr(int** c)
{
*c=*c+1;
}
void foo_int_ptr_ref(int*& c)
{
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ptr(&c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ref(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
}
Output:
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808b0, *c=INVALID PTR
&c=0x7e02d81808b8, c=0x7e02d81808b4, *c=INVALID PTR

there is a mistake in your thinking about this ..
int *c = &a;
this doesn't mean that c "contains" address of a, this means that c is a pointer TO the address of a. Passing a pointer to foo() will not do anything.

Related

How to keep the address stored in a pointer passed as an argument consistent across all function calls

I can pass any argument by reference and the changes to that variable in any of the function calls are reflected in other function calls too.
Likewise if I want to keep the address stored in a pointer consistent across all the function call such that it behaves like we are passing a pointer by reference.
You can pass pointers by reference too, as suggested in a comment.
#include <iostream>
void f(int * & p) {
std::cout << p << std::endl;
}
int main() {
int x;
int * p = &x;
std::cout << p << std::endl; // This prints the same...
f(p); // ... as this.
}

Assignment of integer variable address to class pointer [duplicate]

This question already has answers here:
What will happen when I call a member function on a NULL object pointer? [duplicate]
(6 answers)
Closed 4 years ago.
#include<iostream>
using namespace std;
class Child {
public:
int b;
void gotoSchool() {
cout << "going to school";
}
};
int main( )
{
int a;
Child *p2 = (Child *) &a; // #2
p2->gotoSchool();
return 0;
}
The output of this code is
going to school
but how is this working? How can an integer be typecasted to a user-defined class? Explain to me the concept behind this scenario, please.
What you are doing there is just casting an address and not an integer. For your computer an integer is a serie of bytes (4 bytes in a 32bits processor), let's put it a value of 8. This integer has an address (4 bytes in a 32bits processor too), let's say that the value of that address is 1.
In your code you are casting the address of a. So, pointer p2 has its address. A pointer is an address by definition. The arguments that your class "Child" will take in the casting are the byte values after "a" until it fills its data. In this case, the data is a single int, so the value of "a" and the value of Child "b" is going to be the same one. A pointer as it is just a memory address can be whatever type (consider a class a type you want). The type only tells to the pointer what is the size of the data, and how to interpret it. Now you have been unlucky and the type fits perfectly with the integer. But usually the behaviour of such casting is unespected.
I have modified your code in order to ilustrate what is happening, I think you will see it much more clear after executing it
#include<iostream>
using namespace std;
class Child {
public:
float b;
Child(){ b = -0.5;};
void gotoSchool(){
cout<<"going to school" << endl;}
void changeValue(){ b = -0.5;};
void displayB()
{
cout << "the value of b is " << b << endl;
};
};
class OriginalChild {
public:
int b;
void gotoSchool(){
cout<<"going to school";}
};
int main( )
{
int a = 8;
Child *p2 = (Child *) &a; // #2
OriginalChild *p3 = (OriginalChild *) &a;
p2->gotoSchool();
cout << a << endl;
p2->displayB();
cout << p3->b << endl;
p2->changeValue();
cout << a << endl;
return 0;
}

C++ - Can the following code cause undefined behavior? [duplicate]

This question already has answers here:
Calling a function pointer whose assigned function has less arguments then the pointer type
(2 answers)
Closed 7 years ago.
take a look at the following example:
#include <iostream>
#include <string.h>
void Func1(int x)
{
std::cout << "I'm function 1: " << x << std::endl;
}
void Func2(int x, const char* str)
{
std::cout << "I'm function 2: (this is arg1: " << x << " - args2: " << str << ")" << std::endl;
}
uintptr_t GetProcAddress(const char* _str)
{
if (strcmp(_str, "func1") == 0)
{
return reinterpret_cast<uintptr_t>(Func1);
}
else
{
return reinterpret_cast<uintptr_t>(Func2);
}
}
int main()
{
typedef void(*PROCADDR)(int, const char*);
PROCADDR ext_addr = nullptr;
ext_addr = (PROCADDR)GetProcAddress((const char*)"func1");
//call the function
ext_addr(10, "arg");
std::cin.get();
return 0;
}
We are basically calling Func1 with 2 arguments and can switch to call Func2 with the same args and everything works as intended.
Of course the address of both the arguments are always pushed on to the stack even though the second one is never used by the function itself.
Now I understand that the above code should never be used in production-code but my main question is, can the above code cause UB or is the code always expected to act like that?
Best regards
xx
Yes, it's undefined behavior. From [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling
a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined.

double & and move function in C++

I would like to use parameter in C++ to store back whatever value/object.
In this example, I try to store the value from the global variable as a simplified example.
This code doesn't work,
int value = 20;
void returnPointer2(int* hello)
{
hello = &value;
}
// It changes nothing
int value2 = 100;
returnPointer2(&value2);
cout << value2 << endl;
as I needed double pointer.
void returnPointer3(int** hello)
{
*hello = &value;
}
int* vp2 = new int();
*vp2 = -30;
returnPointer3(&vp2);
cout << *vp2 << endl; // expects 20
I reminded of the reference, and I can use pointer reference to get the same result.
void returnPointer4(int* & hello)
{
cout << "value : " << value;
hello = &value;
}
int* vp3 = new int();
*vp3 = -130;
returnPointer4(vp3); // also expects 20, but much simpler to use
cout << "better : " << *vp3 << endl;
I tried with double &, and it compiles.
void returnPointer5(int&& hello)
{
cout << "value : " << value;
hello = value;
}
However, it doesn't compile with the input of integer variable.
int vp4 = 123;
returnPointer5(vp4); // also expects 20, but even more simpler to use
cout << "best : " << vp4 << endl;
This is an error message.
pointer_return.cpp:31:6: error: initializing argument 1 of 'void returnPointer5(int&&)'
void returnPointer5(int&& hello)
I happened to know about move, and it works with this code.
int vp4 = 123;
returnPointer5(move(vp4)); // also expects 20, but much simpler to see
cout << "best : " << vp4 << endl;
What's the magic/logic behind this move function?
There is a lot of stuff getting mixed in here, but to keep it simple I'll address your root question.
&& is nothing at all like **.
&& is an rvalue reference, while ** is a pointer to a pointer.
As a second point, you are declaring in your function name what you want to do: returnPointer4.
You want to have a pointer to an integer returned back. int*& is the correct syntax for having a reference to a pointer.
Reading over your question again, why don't you use the following:
int& returnGlobalReference() {
return value;
}
Then in your other function:
int& value2 = returnGlobalReference();
The first attempt makes the classic mistake of passing a pointer by value, modifying its address in the function and expecting what it points to to change.
As mentioned in the comments,
void returnPointer2(int* hello)
{
hello = &value; // don't do this, it only modifies what the
// pointer hello, which resides in the stack, points to
*hello = value; // do this instead. even though hello still resides in the
// stack, you're modifying the location that hello points to,
// which was your original intention
}
why do you want to pass pointers however? is the static variable not available when you call the function? (perhaps, different files?)
The magic of std::move is:
The actual declaration for std::move is somewhat more involved, but at its heart, it's just a static_cast to an rvalue reference.
Taken from here.
As Jeffery Thomas already said, a && is not a reference to a reference, but a reference to a rvalue.

Constructor, Copy Constructor and Stack Creation : C++

This question is regarding Function Stack Creation.
Suppose we create a function fn(int a,char b) and call from main fn(A,B) , in this case when the function is called a fn. stack is created with return address, Stack pointer (etc) where local variables and parameters are created and on return is destroyed.
I have a few questions:
1) For our parameterized constructor suppose
myClass{
int a;
char c;
public:
myClass(int a,char c)
{
this->a=a;
this->c=c;
}
};
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c.
2) Now suppose we are calling by reference : my function is fn(int* a,char* b) or fn(int& a, char& b) and calling from our main by fn(&A,&B) and fn(A,B) respectively , in this case also, a function stack will be created with return address,SP etc. My question is that, will a local pointer or reference be created on stack in this case (i.e. creating a local copy of pointer or reference that will point to the passed object). Or is it that no local copy of object is created and the original object pointed by the pointer or the refence is directly passed?
3) Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
Thanks
EDIT
#include <iostream>
using namespace std;
void fn(int , char);
//void fn (int* a, char* c);
void fn (int& a, char& c);
int main()
{
int a=10;
char c= 'c';
cout << "Inside main()" << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
fn(a,c);
//fn(&a,&c);
fn(a,c);
return 0;
}
void fn (int a, char c)
{
int tempInt;
char tempChar;
cout << "\n\nInside Call By Value Function " << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
cout << hex << "&tempInt : " << &tempInt << endl;
cout << hex << "&tempChar : " << (int *)&tempChar << endl;
}
/*void fn (int* a, char* c)
{
cout << "\n\nInside Call By Pointer Function " << endl;
cout << hex << "*a : " << a << endl;
cout << hex << "*c : " << (int*) c << endl;
}
*/
void fn (int& a, char& c)
{
cout << "\n\nInside Call By Reference Function " << endl;
cout << hex << "*a : " << &a << endl;
cout << hex << "*c : " << (int*) &c << endl;
}
Output:
$ make
g++ -Wall Trial.cpp -o Trial
Trial.cpp: In function `int main()':
Trial.cpp:19: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
Trial.cpp:21: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
make: *** [Trial] Error 1
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c
Yes, a function stack is created but a and c are not local variables to the function stack, they are member variables and there lifetime does not end with the end of the constructor. They remain alive throughout the lifetime of the class instance whose member they are.
Or is it that no local copy of object is created and the original object pointed by the pointer or the reference is directly passed?
This is known as pass by reference. The two ways are:
Passing the address of the object or
Pass the object by a reference
In either case the copy of the object is not created. The actual object can be modified within the function, In case 1 the pointer in the function points to the address of the object being passed while in case 2 the reference argument is merely an alias to the object being passed.
Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
No, you cannot because the compiler cannot understand which function version you intend to call when you call it as:
int i = 10;
int j = 20;
fn(i,j);
I misread, as fn(int& a,int& b) and fn(int a,int b) instead of fn(int& a,char& b) and fn(int a,int b).
Ofcourse you can. They have distinct types and hence qualify as valid overloaded functions.
To begin with, your concept is slightly incorrect.
i.e. Stack is not created with a function call. Rather each thread of execution has its own stack already. It is even there when a single main is called. However an ACTIVATION record is pushed on the stack when a function is called. And the same is popped when returning from a function.
So for
Stack is already there and an activation record is pushed on the stack for each function call. The variables live throughout the lifetime of the object.
If your function takes a pointer as argument (i.e. call by reference), there will be a pointer variable pushed on the stack which is passed the address of the original variable. The original variable remains intact and modifying its value via pointer would change the original variable.
You can only overload functions when their signatures are different. This means type, number or order of parameters. In the e.g. you quoted, it is not possible to differentiate whether a passed int is a variable or it is an address of a variable. Hence this overload won't work.
EDIT: Point 3 above has as slight mistake. The e.g. quoted in question has second parameter different and hence qualifies as valid overload. Note that the criteria is not just the name of data type (i.e. int vs. int * is also different types), but rather the fact that given an input value, compiler should be able to differentiate and chose which overloaded version to call.