Is Passing Pointer Argument, Pass by Value in C++

Is passing pointer argument, pass by value in C++?

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.

Is passing pointer by value or by reference the same

What is the difference between passing a pointer by reference and passing a pointer by value in C?

There is no such thing as passing a pointer by reference in C, all variables are passed by value, even pointers.

My understanding is when you pass arguments to methods a new stack frame is created and those values are copied to different memory addresses unless passed by reference. If passed by reference the memory addresses are passed.

Again, the pointers are not passed by reference, a copy of the value stored in the pointer is passed, i.e. the address where it points to, you can test this by changing the value of the pointer inside the function, and check how that reflects on the original pointer, spoiler, it doesn't.

When working with pointers I noticed that if I pass a char by value and modify it in a different stack frame when I return back to the main stack frame the value of the ptr has been modified.*

What you are passing is an address, a memory location where some data is stored, when you change the data stored in that memory address it will be permanent, no matter where you do it, in fact that is one of the advantages of using pointers, for you to change the contents of some variable outside the scope where it's declared.

Return Value or Passing Pointer as Argument?

1) Do I have to pass pointers as argument if I can just use return value to achieve the same result?

No, you don't always have to. But observes that it frees up the return value of the function for error reporting. A very simple example:

enum error_code {
E_SUCCESS,
E_GENERAL_FAILURE,
E_MEMORY_ALLOCATION_FAILED,
E_INVALID_ARGUMENT,
E_FILE_NOT_EXIST
};

struct my_important_data {
// stuff
};

enum error_code fill_important_data_from_file(char const *file_name,
struct my_important_data **data)
{
if(!data || !file_name)
return E_INVALID_ARGUMENT;

*data = malloc(sizeof(**data));

if(!*data)
return E_MEMORY_ALLOCATION_FAILED;

// Return different error codes based on type of failure
// so the caller can know what exactly went wrong

return E_SUCCESS;
}

2) I observe when I print the address of the memory of variable 'x' from the function that returns value, the memory address is very short 0xb , any idea why? normally the address is very long.

That's because you are using the %p conversion specifier to print a regular int, and not an actual address. Strictly speaking that's causing the printf function to have undefined behavior.

Are pointers passed by value in C++?

  1. When the control is inside foo(), is a == *ptr && a == 1?

Yes. The parameter a is copy-initialized from the argument *ptr, its value would be same as *ptr, i.e. 1.


  1. When the control is inside bar(), is b == ptr?

Yes. The parameter b is copy-initialized from the argument ptr, its value would be same as ptr.


  1. When the control is inside bar(), is &b == &ptr?

No. They're independent objects and have different address.


  1. If your answer to Q.3 was false then is there even anything as a call-by-reference in C++?

Yes. You can change it to pass-by-reference.

int bar(int *&b);

Then the parameter b would bind to the argument ptr, it's an alias of ptr; then &b == &ptr is true.

At last,

Are pointers passed by value in C++?

Yes, they're passed by value themselves. The logic is the same as foo as you noticed.

EDIT

Would you comment on whether class_name* &b is useful in any scenario?

Just as other non-pointer types being passed by reference, it's useful if you want to modify the pointer itself (not the pointee) in the function. e.g.

int bar(int *&b) {
b = ...; // make b pointing to anything else
// the orginal pointer argument being passed gets changed too
}

What is wrong in passing pointer variable as an function argument instead of address of variable in C?

The function parameter p

void fun(int *p)
{
p = &b;
}

is a local variable of the function. The function deals with a copy of the value of the pointer passed to the function

fun(p);

So within the function it is its local variable that is changed.

You may imagine the function and its call the following way (I will rename the function parameter to ptr for clarity)

fun(p);

//...

void fun( /* int *ptr */ )
{
int *ptr = p;
ptr = &b;
}

As you can see the original pointer p was not changed.

If you want to change the pointer you need to pass it by reference. In this case the function will look like

void fun( int **p)
{
*p = &b;
}

and in main it is called like

fun( &p );

In this case the pointer p (and not a copy of its value) will be indeed changed in the function.

That is the general rule is if you want to change an object in a function you nned to pass it to the function by reference. In C passing by reference means passing an object indirectly through a pointer to it. In this case dereferencing the pointer you will get a direct access to the original object.

pass by reference and value with pointers

Whilst something like this does what you expect:

void func(int *p)
{
*p = 1;
}

int a = 2;
func(&a);
// a is now 1

this does not

void func(int *p)
{
p = new int;
}

int *p = NULL;
func(p);
// p is still NULL

In both cases, the function works with a copy of the original pointer. The difference is that in the first example, you're trying to manipulate the underlying integer, which works because you have its address. In the second example, you're manipulating the pointer directly, and these changes only apply to the copy.

There are various solutions to this; it depends on what you want to do.

Passing pointer of a pointer in C

TL/DR - For what you're trying to do, helperFunction1 and helperFunction2 are declared correctly, you just need to use the correct names in helperFunction1.

Longer version

If you want your function to modify the pointer object itself, then you must pass a pointer to that pointer. Here's a contrived example where we want to update a FILE * object:

void open( FILE **ptr, const char *name, const char *mode )
{
*ptr = fopen( name, mode );
}

int main( void )
{
FILE *in; // in stores the address of a FILE object
FILE *out; // out stores the address of a FILE object

open( &in, "input.txt", "r" ); // we are changing the values of in and out
open( &out, "output.txt", "w" ); // so we must pass pointers to those objects
...
}

We want open to modify the objects in and out, so we pass pointers to those objects.

Compare that to something like this:

void write( FILE *ptr, const char *text )
{
fwrite( ptr, "%s", text );
}

In this case, we're not trying to change the file pointer itself, we're just trying to write to the FILE stream it points to, so we don't need to worry about a pointer to a pointer in this case. Another contrived example:

int main( void )
{
FILE *out;
...
write( out, "some text" ); // we are not changing the value of out,
... // so we do not pass a pointer to it
}

For any type T, if we want a function to modify an object of that type, we must pass a pointer to that object:

void foo( T *ptr )
{
*ptr = new_T_value(); // write a new value to the thing ptr points to
}

int main( void )
{
T var;
foo( &var ); // write a new value to var
}

This works exactly the same way for pointer types - replace T with P *:

void foo( P * *ptr ) // or just P **ptr
{
*ptr = new_Pstar_value(); // write a new *pointer* value to the thing ptr points to
}

int main( void )
{
P * var;
foo( &var ); // write a new value to var
}

Again, this is only true if you want to modify the value of var.

You can go with even higher levels of indirection - replace P with Q *:

void foo( Q * * *ptr ) // or just Q ***ptr
{
*ptr = new_Qstarstar_value(); // write a new *pointer* value to the thing ptr points to
}

int main( void )
{
Q * * var; // or just Q **var
foo( &var ); // write a new value to var
}

The expression *ptr in foo has the same type as the expression var in main, so writing to *ptr is equivalent to writing to var.



Related Topics



Leave a reply



Submit