Search code examples
cpointerspass-by-referencepass-by-valuedouble-pointer

Why single pointer as argument can't modify a string (in c)


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;
}

Solution

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