1

By using a double pointer as argument in a function, the program below can modify the string, I understand.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void display(char** output)
{
    printf("%s\n", *output);
    *output = "This is another test";
}

int main(void)
{
    char* str = "This is a test";
    display(&str);
    printf("After the call: %s\n", str);
    return 0;
}

However, I don't understand why using a single pointer as argument like below can't modify the string.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void display(char* output)
{
    printf("%s\n", output);
    output = "This is another test";
    printf("%s\n", output);
}

int main(void)
{
    char* str = "This is a test";
    display(str);
    printf("After the call: %s\n", str);
    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Fary
  • 77
  • 4
  • 2
    In c arguments are always passed by value. In the 2nd you pass the pointer itself. It is passed by value and therefore changing `output` in `func` modifies the copy and does not affect the caller. In the 1st one you still pass by value (as always), but you pass the address of the pointer. Using the address you can modify the pointer of the caller (`*output = ...`). – wohlstad Apr 21 '23 at 08:37
  • Why can you modify the pointer by using an address of a pointer in function? – Fary Apr 21 '23 at 08:43
  • 1
    See https://stackoverflow.com/questions/39486797/dynamic-memory-access-only-works-inside-function, the answer explains it. – Lundin Apr 21 '23 at 08:57
  • 1
    Be aware that in C *all* parameters are passed *by value* to functions. This means the values are *copied*. Always, full stop. This applies for pointers as well. So if you assign to the parameter in second example you modify the copy. This applies for the double pointer, too, if you do not dereference it. On dereferencing you modify that this double pointer points to – and this is the single pointer outside the function... – Aconcagua Apr 21 '23 at 08:57
  • 1
    Note, that you – albeit legal – shouldn't ever assign string literals to pointers to non-const char! That way you run the risk of accidentally modifying them, which is undefined behaviour. And if your code gets complex you *will* end up doing so some day... – Aconcagua Apr 21 '23 at 09:00
  • Also read this https://stackoverflow.com/questions/766893/how-do-i-modify-a-pointer-that-has-been-passed-into-a-function-in-c – Jabberwocky Apr 21 '23 at 09:03

2 Answers2

4

You may imagine the function and its call in the second shown program the following way

char* str = "This is a test";
display(str);

//...

void display( /* char* output */ )
{
    char *output = str;

    printf("%s\n", output);
    output = "This is another test";
    printf("%s\n", output);
}

That is the argument expression str is used to initialize the function local variable output. And within the function it is its local variable output that is being changed. The pointer str used as an initializer of the function local variable stays unchanged. The function does not deal with str except of using it to initialize its parameter output.

To change an object within a function you need to pass it to the function by reference.

In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer the function has a direct access to the object pointed to by the pointer and can change it. And your first program demonstrates this approach.

Dereferencing the pointer output

*output = "This is another test";

the function has a direct access to the pointer str declared in main and passed to the function through a pointer to it

display(&str);

and changes it.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

You can't assign an argument in function.

void func(int* a) {
    int b = 0;
    *a = b; // that'll work.
    a = &b; // that doesn't.
}

Use a char** to do what you want.