fiksx
fiksx

Reputation: 178

Understanding pass pointer to pointer in function by reference

void func(char *ptr)        //Passed by      reference
{
  *ptr = 'B';
}

int main()
{
  char *ptr;
  ptr = (char *) malloc(sizeof(char) * 1);
  *ptr = 'A';
  printf("%c\n", *ptr);

  func(ptr);
  printf("%c\n", *ptr);
}

I was confuse I know that ptr=(char*)malloc (sizeof(char*1) here means allocate 1 byte and return a pointer to the allocation then assign to ptr, so ptr is a pointer.

But when it calls func(ptr) why it not use &? Although what I want is to change the character inside ptr points to? Why not using void func(char** ptr) and send func(&ptr) here? Is it possible?

I mean what made this pass by reference?

second code:

#include <stdio.h>

#include <stdlib.h>
int main()
{
    char *c=NULL;
    test(c);
    printf("after test string is %s\n",c);
    return 0;
}

void test (char *a)
{
    a=(char*)malloc(sizeof(char)*6);
    a="test";
    printf("inside test string is %s\n",a);
}

Upvotes: 0

Views: 1960

Answers (3)

In C there is really no such thing as "pass by reference". All arguments are passed by value - assigned as copies into the local variables - the parameters. Given a function like

void func(char *ptr);

the value passed in is a char * - a pointer to char, and within the function, the value stored in ptr is a copy of the original value in the calling function, so that no changes in the value of ptr itself within the callee would be seen outside in the caller.


But the value of that pointer - if it is valid - is also a reference to an object of type char - or to an element of an array of type char[]. In your case, it is the pointer to the first element of dynamically allocated array of 1 characters. Thus you indeed passed in - by value - a reference to an object of type char.


Had you used func(&ptr); the function prototype would need to be

void func(char **ptr);

that is, the argument would have to be a pointer to a pointer to char. If you dereference the value once, with *ptr, you get an lvalue (locator value) of type char *; you can modify this as if it was a a variable. Or, you can dereference that pointer value too - i.e. **ptr to get an lvalue of type char.

However, in the case of your function, if you just want to modify the stored char, the change wouldn't have helped a bit, but instead make your code more complicated to use, as you'd now need a valid object of type char *, whose address would be passed into the function; with void func(char *ptr), you just need a valid object of type char.

Upvotes: 1

Mike Nakis
Mike Nakis

Reputation: 61969

Of course it is possible to do void func( char** ptr ) and invoke it with func( &ptr ), but then you would not (only) be passing the character by reference, you would be passing the pointer by reference. So, in order to change the character, you would need to do **ptr = 'B'; inside func().

But if all you want to do is change the character pointed by ptr, then the additional level of indirection does not buy you anything.

You would use void func( char** ptr ) if you were planning to change the address that the pointer points to. That would look like this:

char b;

void func( char** ptr )
{
    *ptr = &b;
}

Upvotes: 0

Vivick
Vivick

Reputation: 4991

When you call func using ptr as its parameter you are actually passing a char* (since ptr is a char*).

If you were to use func(&ptr) you'd pass a pointer to a pointer (here a char**) but func requires a pointer to a char (char*).

You can use void func(char**) and func(&ptr) but that would just add a "layer of pointer" for seemingly no reason (since in func you want to access the content you'd have to do **ptr).

The call is pass-by-reference because you pass in a pointer (variable that holds the address in memory of another variable) not a value (variable itself).

Upvotes: 1

Related Questions