Как установить ссылку указателя через функцию

В C я пытаюсь установить значение указателя, отправив его функции, но значение не изменится вне функции. Вот мой код:

#include <stdio.h>
void foo(char* str) {

    char* new_str = malloc(100);
    memset(new_str, 0, 100);
    strcpy(new_str, (char*)"new test");

    str = new_str;
}


int main (int argc, char *argv[]) {

    char* str = malloc(100);
    memset(str, 0, 100);

    strcpy(str, (char*)"test");

    foo(str);

    printf("str = %s\n", str);
}  

Я хочу распечатать:

str = new test 

но этот код печатает:

str = test

Любая помощь будет оценена. Спасибо заранее.

Ответ 1

Нет пропусков в C. Если вы предоставляете str в качестве аргумента функции в C, вы всегда передаете текущее значение str, никогда str.

Вы можете передать указатель на str в функцию:

void foo(char** pstr) {
    // ...
    *pstr = new_str;
}

int main() {
    // ...
    foo(&str);
}

Как говорит Эйко, ваш пример кода утечки первого распределения памяти. Вы больше не используете его, и у вас больше нет указателя на него, поэтому вы не можете его освободить. Это плохо.

Ответ 2

Вам нужно использовать указатель на указатель, untested:

#include <stdio.h>

void foo(char** str)
{
    char* new_str = malloc(100);
    memset(new_str, 0, 100);
    strcpy(new_str, (char*)"new test");
    if (str) { /* if pointer to pointer is valid then */
        if (*str)   /* if there is a previous string, free it */
            free(*str);
        *str = new_str;  /* return the string */
    }
}


int main (int argc, char *argv[])
{
    char* str = malloc(100);
    memset(str, 0, 100);

    strcpy(str, (char*)"test");

    foo(&str);

    printf("str = %s\n", str);
}

Ответ 3

Вы просто переназначаете указатель, который является локальной переменной в foo.

Если вы хотите скопировать строку, используйте strcpy(str, new_str);

Вместо этого вы можете передать ссылку на указатель и переназначить ее, но это может легко привести к утечкам памяти и ее трудно поддерживать.

Изменение: Для псевдо передачи по ссылке см. ответ стива.

Ответ 4

Я сделал это таким образом, возвращая указатель из функции. В этом случае нет причин использовать malloc, поэтому вам не нужно беспокоиться об освобождении.

gcc 4.4.3 c89

char* print_test(char *str)
{
    char *new_str =  "new_test";
    printf("new_str [ %s ]\n", new_str);
    str = new_str;
    return str;
}

int main(void)
{
    char *str = "test";

    printf("str [ %s ]\n", str);

    str = print_test(str);

    printf("str [ %s ]\n", str);

    return 0;
}