2010-08-19 2 views
10

В 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 

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

ответ

17

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

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

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

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

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

+0

"Существует не передача по ссылке в C" - не является массивы передаются по ссылке? – naivnomore

+0

@naivnomore В основном вы передаете указатель, который (по крайней мере синтаксически) отличается от передачи ссылок в C++. – Eiko

+1

Нет, это не так. Массивы распадаются на указатели при передаче в качестве параметров, но это все равно не является передачей по ссылке, потому что изменение значения самого аргумента указателя не влияет на массив. –

3

Вы должны использовать указатель на указатель, непроверенный:

#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); 
} 
+0

Вероятно, вы имеете в виду 'if (str)', а не 'if (* str)'. Хотя даже с этим изменением, в случае, когда 'str' имеет значение null,' foo' утечки распределения. –

+0

@Steve: oops. Благодарю. исправленный. – Dummy00001

+0

Также: 'free (0)' ничего не делает. Но на самом деле неправильно проверять значение null перед вызовом 'free'. –

2

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

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

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

Редактировать: Для псевдопрохода по ссылке см. Ответ от Стива.

1

Я сделал это так, вернув указатель из функции. В этом случае нет причин использовать 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; 
} 
Смежные вопросы