Is passing pointer argument, pass by value in C++? Since i see that any change to the pointer as such is not reflected outside the method. The changes i do by dereferencing the pointer is reflected though.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
Yes to both.
Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied. That means that if you change the value of the pointer in the function body, that change will not be reflected in the external pointer that will still point to the old object. But you can change the value of the object pointed to.
If you want to reflect changes made to the pointer to the external pointer (make it point to something else), you need two levels of indirection (pointer to pointer). When calling functions it's done by putting a & before the name of the pointer. It is the standard C way of doing things.
When using C++, using references is preferred to pointer (henceforth also to pointer to pointer).
For the why references should be preferred to pointers, there is several reasons:
references introduce less syntaxic noise than pointers in function body
references keep more informations than pointers, than can be useful for compiler
Drawbacks of references are mostly:
they break the simple pass-by-value rule of C, what makes understanding the behavior of a function regarding of parameters (will they be changed ?) less obvious. You also need function prototype to be sure. But that is not really worse than the multiple pointer levels necessary when using C.
they are not supported by C, that can be a problem when you write code that should work with both C and C++ programs (but that's not the most usual case).
In the specific case of pointer to pointer, the difference is mostly simplicity, but using reference it may also be easy to remove both levels of pointers and pass only one reference instead of a pointer to pointer.
I understand the confusion here. The concepts of "pass by value" and "pass by reference" are not so clear even if they seem to be so.
Bear in mind that the computer does not know these concepts and does not behave according to it.
The computer does not know about the types. Hence it does not make a distinction of pointers and values.
Let me try to explain by and example:
void func1(int x) //copy some value to local variable x (of type int)
{
x = 5; //modify local variable. lost after function call
}
void func2(int *x) //copy some value to local variable x (of type int*)
{
int a;
x = &a; //modify local variable. lost after function call.
}
void func3(int *x) //copy some value to local variable x(of type int*)
{
*x = 10; //x is local but *x is not! change is saved after function call!
}
func1 and func2 are identical. Both modify a local variable. Modification is lost after function is popped off the stack.
func3 has ability to change another memory location (a variable which is not local to the function).
basically, every function call is "call by value". But in the case of a pointer type, we have a way to change the content of a remote address in memory.
Pass by value using Pointers
I'll explain it by example:
void f(int *ptr)
{
cout<<*ptr;
}
int main ()
{
int a=10;
int *aptr=&a;
f(aptr);
return 0;
}
Here, in main function a is an integer variable whose content is 10 and address is 00F8FB04 (assume).
aptr is pointer to integer, that store the address of integer variable a, so aptr content is address of integer variable a that is 00F8FB04. When we pass aptr as the function argument only content of aptr (that is address) are copies to function parameter.
So, ptr will receive the copy of content of aptr (that is address 00F8FB04)
Either a pointer to a pointer, or a reference to a pointer, is what you would use if you wanted to potentially change the pointer itself. To your original question, technically, yes, all parameters are passed by value.
Yes it is, as it is in C.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
In which case? What do you want? You can use real references with the & modifier.
void func(type &ref);
Related
I have a function that takes a char **; it uses it internally for maintaining context between successive calls.
What is the difference between defining char **x and passing x to it, and defining char *x and passing &x?
For context: I tried to implement the example at strtok man page on my own before reading the source code. And I got segfaults. Then after attempts I looked at the source.
The problem was that I defined char **x and passed x as the **saveptr argument, but changing the definition to char *x and the passing to &x solved the problem.
What is the problem exactly?
The first version, with char **x; and passing x, creates and uses an uninitialised pointer to pointer to char.
The second version, with char * x; and passing &x, creates an uninitialised pointer to char, but passes a value which is a valid address of a pointer to char, and is a defined value (i.e. like an initialised pointer to uninitialised pointer to char).
Basically with first version you ask to write at a "random" place in memory (almost sure way to get a segfault); with second, you ask to write into an existing pointer variable.
When you define e.g.
char **x;
Then you simply define a pointer. It doesn't matter that it's a pointer to another pointer, the important part is that it's just a pointer. And as such, with the definition shown above, it's not initialized. It doesn't point anywhere special. Dereferencing it, like you most likely do in the function, leads to undefined behavior.
On the other hand, with a definition like
char *x;
and using &x to get a pointer to it, the pointer returned by &x points somewhere valid, to the variable x. Dereferencing &x will allow the function to access and modify x itself.
Using the address-of operator in this way is a way to emulate pass by reference, which C doesn't have.
Because all function arguments are passed by value in C, if you define char **x and pass x, it won't be modified by the function. If you define char *x and pass &x, it can be modified (change its pointing address).
I know that this code:
void incVar(int i){
i++;
}
We know this will create a copy of the integer and then increase that value, but not the actual value.
By nature: Methods in C create copies of parameters in their Stack Frame and not the original variable.
But:
void incVar(int *i){
(*i)++;
}
Is supposed to increase the actual value of the integer by the pointer dereference.
But then, why doesn't C just create a copy of the pointer *i instead? If this is the normal behavior with regular integers, then why doesn't the same thing happen with pointers?
It is the same with pointers. All variables in C are passed by value, even pointers.
You copy the address stored in the pointer outside the function, into its parameter.
But you can use that address to reference a variable which can be allocated anywhere. So in the following code:
int j = 0;
incVar(&j);
incVar receives by-copy the address of j. But it can use that address to read or modify j (in)directly.
In fact the same thing as with values happens with pointers. Just make sure to understand the syntax correctly. You are not passing the integer *i by copy to incVar, but you are passing the pointer i of type int* by copy. No matter how often you copy the pointer to an address, it always points to the same address. So i in your second incVar example points to the integer the caller took the address of. So by derefencing the copy of the pointer (in (*i)++), you are acessing the integer of the caller.
Its better to see int *i; as a variable named i of type pointer-to-int, instead of a pointer named *i.
In your example:
void incVar(int *i) {
(*i)++;
}
We probably use it as such in the main function:
int a = 5;
incVar(&a); //After this line, a is now 6.
What happens in incVar(..) is this:
A variable i is created, of type pointer-to-int.
It holds a copy of the value of &a.
Although i is a copy, its value is the same as that of the value of &a, and it still points to the same integer a.
As a result, by de-referencing i, I refer to the integer a.
Increment the integer a, which obviously is at the address pointed to by i.
I have this function signature:
void myFunction(int *const ptr);
What's the point of the const keyword in this particular context?
Even if ptr wasn't a const variable, I couldn't modify to what address it points to, because it's passed by value, so if I had another function like this:
void myAnotherFunction(int *ptr);
And inside its implementation did something like this:
//...
ptr = malloc(1023);
//...
This wouldn't affect the passed value (outside this function, of course).
So the question is: what's the point of using myFunction() signature instead of myAnotherFunction() one? (beside that you get a compile-time error).
ptr = malloc(1023);
This wound't affect the passed value (outside this function, of
course).
To sum up. Indeed that way original pointer would not be affected (it would still point to same object because ptr is copy of the original pointer), but you can still make that pointer point to a different object inside myAnotherFunction and change value of that object through that pointer. e.g. in myAnotherFunction you could do:
ptr = &y;
*ptr = 9;
Whereas in the first case when you have a constant pointer, you can't assign a new address to it, but you can still change the value of object to which it points using dereferencing. A constant pointer means you can't assign a new address to it, pointer to a constant object means you can't change value of object to which it points, but you can assign new address to the pointer.
It might make more sense if you consider that the function
void myFunction(int *const ptr);
might be manipulating many pointers, and assigning them and reassigning them, and an invariant of the algorithm it is executing is that the input pointer should never be changed. Then, labeling it const might be very helpful, or at least make you feel more confident that its been implemented correctly.
This question already has answers here:
change pointer passed by value
(6 answers)
Closed 7 years ago.
I had a programming assignment a while back where I stumbled upon this little problem: when I gave a function a pointer as a parameter, I could not change the address it pointed at. I solved that by returning the new adress I wanted the pointer to point to. But I am still wondering why it's not possible to manipulate a pointer parameter because all memory allocating functions work with a return value as well instead of a parameter list.
Was I possibly doing something wrong? Or is it really not possible to change the pointee? Does anyone have an explanation?
Example:
void foo(int *ptr)
{
ptr=malloc(sizeof(int));
} /* after calling this function I would
expect the pointee to have changed to the
newly allocate memory but it stays NULL*/
int main()
{
int *ptr=NULL;
foo(ptr);
return 0;
}
It's because all parameters are passed by value in C. If you call a function with a pointer parameter you may change that pointer in the function but this will have no effect on the caller's value of the pointer.
If you need to communicate a modified pointer back to the caller, returning the modified pointer is the way to go. Note that this also only passes a value back.
Another way would be to pass the address of a pointer (i.e. a pointer to a pointer). The called function can then store a new pointer value at the given address.
Memory allocating functions return the pointer value, so it is generally
assigned to a pointer.
Passing a pointer to a function as an argument is a different story,
because changing it won't change the original (pass by value). That's
why we use pointers in these cases, to give the address of a variable
and change its value in the function.
If you need to pass a pointer instead, and change what it points to, use
a pointer to a pointer!
void
my_function(int **pointer)
{
*pointer = &something; // will change the pointer address
}
int *my_pointer = &something_else;
my_function(&my_pointer);
If I had a function defined arbitrarily like:
char* myfunction(int, int[]);
which, as shown, returns a character pointer. Do you have to write in the calling function something like:
char *ptr = myfunction( ... );
Or is there a way to use the pointer that is returned by the function without creating another pointer to the one returned?
I ask because, given how I described above, you essentially have a pointer returned, and another pointer assigned to that one. Thus, you then have an unused pointer (the one returned by the function) taking up memory.
If there is no way to explicitly use the pointer that is returned, is there a way to assign a new pointer to the returned pointer and free the unused one?
A pointer is a really small thing. It's just a representation of the address of an object. You shouldn't be concerned about creating extra copies of a pointer (it's like creating an extra int).
char* foo() {
char* bar;
// some stuff that mallocs a value and assigns to bar
return bar;
}
char* x = foo();
In the simplified example above, the bar pointer is created on the stack, and the code in the comments points it at some memory in the heap (with a Malloc or something). When the function foo() is evaluated, the value of the pointer (e.g. The address of the memory) is popped off the stack and assigned to x. There is no unused pointer hanging around, it's just been reassigned. The memory that it points to remains exactly where it is and isn't duplicated.
You aren't creating extra copies of the memory that the pointer is pointing to. In fact, that's a large reason to pref pointers, because it involves copying less.
The pointer that is returned by the function doesn't waste memory as you state. When the function returns, and as soon as the affectation ptr = myfunction(...); is done, the returned value doesn't exist anymore in memory.
But to answer your question, yes you can use the returned pointer directly, without a temporary variable. Although it is a rvalue (you can't do myfunction() = NULL for example), the location it's pointing to is at your disposal : *myfunction() = 3 is valid, granted the pointer returned is valid.
I prefer using a temporary variable, as you can reuse the value in 2 or more expressions, and it is far more readable in my opinion.