0
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);
}
fiksx
  • 176
  • 1
  • 15
  • the pointer "ptr" is an integer (it contains the address of some byte). This integer "ptr" is located on the stack. func(ptr) will write "B" into the byte defined by the parameter "ptr". &ptr will give you the address of the integer "ptr" on the stack. I think C would be much less confusing, if there were no "pointer types" but just regular integers instead. – Ivan Kuckir Jun 11 '17 at 09:35
  • func(ptr) means pass pointer and void func(char *ptr) here refer to address? I mean why this can change the value of ptr? Though not pass address of ptr? – fiksx Jun 11 '17 at 10:40
  • Being picky, one has to state that in C *everything* is pass by value. The answer deals with this: https://stackoverflow.com/a/13654139/694576 – alk Jun 11 '17 at 10:56
  • @alk i dont understand why this can change the value of ptr.. func (char*ptr) is this means to get the address of malloc and declare it as pointer? – fiksx Jun 11 '17 at 11:57
  • The code you show does *not* change the value of `ptr`, but the value it points to. Doing `*ptr` dereferences `ptr`, that is it evaluates to the value `ptr` points to, which is `'A'`. Doing `*ptr = 'B'` does not change `ptr` but the content of the memory `ptr`'s value addresses, as returned by the call to `malloc()`. – alk Jun 11 '17 at 12:02
  • Perhaps it helps you understanding what is going on twith `ptr` if you'd printed its *value* several times during the execution of the code you show. To do so use: `printf("ptr = 0x%p\n", (void*) ptr);` – alk Jun 11 '17 at 12:08
  • @alk When call func(ptr) here means pass a pointer to value inside allocation address right? Then what func(char*ptr) means? This just means to declear that ptr is pointer to char? Dereference ptr means to change what is inside the memory address which is A? Is this the same with for example int ptr=5 and i pass an argument func(&ptr) and funct receive void func(int*ptr) and *ptr=6 will change ptr? – fiksx Jun 11 '17 at 12:16
  • Test it. Use the print command as per my last comment to print any pointer value. – alk Jun 11 '17 at 12:18
  • @alk tested it got all same address,still dont know the point – fiksx Jun 11 '17 at 13:02
  • The point is that in your code the value of the pointer variable `ptr` never changes after it had been set the 1st time being assign the result of the call to `malloc()`. – alk Jun 11 '17 at 13:40
  • @alk ok tried to understand, But actually func(ptr) and func(char*ptr) have same meaning here? Means Pointer that is passed is a pointer to char name ptr? – fiksx Jun 11 '17 at 13:52
  • Here `func(ptr)` is the statement calling a function defined as `func(char *ptr)`. As (more or less) 1st thing during this call the value of `ptr` living on calling side is *copied* into another variable `ptr` on the called side (living inside `func()` here). – alk Jun 11 '17 at 14:24
  • @alk so the pointer inside the func is a copy? But the memory address is the same? Thats why the value changed? – fiksx Jun 11 '17 at 14:28
  • Yes, "*that why the value*" of the memory the pointer points to *"changed*". – alk Jun 11 '17 at 14:31
  • @alk i update another code in edit..(please see edit) i try to change to "test" but still i got NULL after the test function? what makes difference here with the first code? – fiksx Jun 11 '17 at 14:37
  • As already mentioned: inside the function the value is a *copy* of what the caller uses. This copy is not passed back up again. So if it's value changes inside the function, then the caller's value does not. – alk Jun 11 '17 at 14:42
  • @alk how to passed back again? Beside that is it possible to write a=(char*)malloc (sizeof(char*1) , *a="test" , why this is wrong? – fiksx Jun 11 '17 at 14:54
  • Read and understand this: https://stackoverflow.com/q/2838038/694576 – alk Jun 11 '17 at 14:56

3 Answers3

1

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).

Vivick
  • 3,434
  • 2
  • 12
  • 25
  • In call by reference if i want to modify what pointer point too, as a parameter i should pass the pointer and the function will expect pointer? While func(char**ptr) means address of ptr? – fiksx Jun 11 '17 at 10:15
  • If you wanna modify what the pointer points to, one layer is enough (you pass the pointer itself). With `func(char** ptr)` you pass the pointer to a pointer (aka the address of the latter pointer). That's why I call the `&` operator the "address accessor" – Vivick Jun 11 '17 at 10:18
  • But i thought this is pass by value.. func(ptr) here pass pointer, void func(char *ptr) here means refer to address? – fiksx Jun 11 '17 at 10:38
  • Is this mean in func(ptr), i pass memory address(which is malloc) and was define as char*ptr in func?? So thats why it work? – fiksx Jun 11 '17 at 10:48
  • It is technically both pass by value and pass by reference. The only thing that matters is the referential : if you want the content of where the pointer points to, it's pass by reference (a reference to the content). If you want the pointer as the content then it's pass by value (since you consider the pointer as the value). In your case it's a pass by reference kinda deal – Vivick Jun 11 '17 at 19:18
  • Indeed you pass the address of a char and you defined the parameter as being an address of a char (therefore the types matches and it works) – Vivick Jun 11 '17 at 19:19
  • so just want to clarify, when i call func(ptr), means pass a copy of a value that store in variable ptr in main ->"value" here means address(malloc) or 'A'? And char*ptr here is somewhere in the memory that different with the one in main right? And what is store inside char*ptr is the malloc(address) so it can directly refer to what is inside malloc right? – fiksx Jun 12 '17 at 02:47
  • When you call `func(ptr)` means that you pass a pointer (address in memory to a variable) by value. But if your use of this pointer is limited to accessing the value pointed by the pointer then you can consider passing a pointer as passing your variable/value by reference. – Vivick Jun 12 '17 at 09:21
  • Okay but suppose i have struct node* head , head is a pointer to struct node and inside it node it pointer to another node and i pass address of pointer head to a function call push, push(&head,1), &head here means pass address of variable head/address that head point to? The function push itself define &head as struct node** – fiksx Jun 12 '17 at 15:26
  • The function accepts `struct node**` , head is a `struct node*` and you pass it to your function as `&node`, as `&node` is a `struct node**` it's all good. – Vivick Jun 12 '17 at 15:35
  • Yeah type matches but (&head) here means the address of variable head or address what is head point to? And what is the different with func(ptr)? – fiksx Jun 12 '17 at 15:37
  • Just understand `&` as adding a "layer of pointer". If you have a type `A` and a variable `A a` then `&a` is of type `A*`. `&x` means the address of `x` (it actually returns a pointer to `x`). – Vivick Jun 12 '17 at 15:40
  • &x here is actually a pointer to x? Is it the real x address? Or is it the address of thing that x holds? Still confuse!!! – fiksx Jun 12 '17 at 21:54
  • `&x` returns an address (which can be passed as a pointer since a pointer holds an address as its value) – Vivick Jun 13 '17 at 23:02
  • Ah okay!! I think i understand, its like making pointer over pointer to access data that the first pointer point to right!!Thanks!!! I was so confuse before but clearer now!! ^^ – fiksx Jun 14 '17 at 08:10
1

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.

  • So i pass pointer which is the reference to dynamically allocated array of 1 char, thats why it can change the value? *ptr here means access the value inside malloc() thats why i can change the value? Instead whats the difference if i call func(&ptr)? – fiksx Jun 11 '17 at 13:37
0

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;
}
Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • If func(&ptr) -> void func(Char**ptr) here point to address of *ptr? *ptr=&b ->*ptr here means value or address? – fiksx Jun 11 '17 at 10:28