2010-08-19 11 views
10

In C, sto cercando di impostare il valore di un puntatore inviandolo a una funzione, ma il valore non cambierà al di fuori della funzione. Ecco il mio codice:Come impostare il riferimento del puntatore tramite una funzione

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

voglio stampare:

str = new test 

ma questo codice stampa fuori:

str = test 

Qualsiasi aiuto sarà apprezzato. Grazie in anticipo.

risposta

17

Non esiste un riferimento pass-by in C. Se si fornisce str come argomento per una funzione in C, si passa sempre il valore corrente di str, mai str stesso.

Si potrebbe passare un puntatorea str nella funzione:

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

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

Come dice Eiko, il codice di esempio, le perdite della prima allocazione di memoria. Non lo stai più utilizzando e non hai più un puntatore, quindi non puoi liberarlo. Questo non va bene.

+0

"Non v'è alcun passaggio per riferimento in C" - non è array passati per riferimento? – naivnomore

+0

@naivnomore Fondamentalmente si passa un puntatore che è (almeno sintatticamente) diverso dai riferimenti di passaggio in C++. – Eiko

+1

No, non lo sono. Gli array decadono ai puntatori quando vengono passati come parametri, ma non si tratta ancora di un riferimento pass-by perché la modifica del valore dell'argomento puntatore non influisce sull'array. –

3

È necessario utilizzare il puntatore al puntatore, non testato:

#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

Probabilmente vuoi dire "if (str)" piuttosto che "if (* str)". Sebbene anche con quella modifica, nel caso in cui 'str' sia nullo,' pippo' perde un'allocazione. –

+0

@Steve: oops. Grazie. corretto. – Dummy00001

+0

Inoltre: 'free (0)' non fa nulla. Ma non è in realtà sbagliato controllare il valore di null prima di chiamare 'free'. –

2

Stai solo Riassegnazione di un puntatore, che è una variabile locale in foo.

Se si vuole copiare la stringa, utilizzare strcpy(str, new_str);

potreste passare un riferimento al puntatore invece e riassegnare, ma questo può facilmente portare a perdite di memoria ed è difficile da mantenere.

Modifica: Per lo pseudo pass per riferimento vedere la risposta di Steve.

1

Ho fatto in questo modo restituendo il puntatore dalla funzione. Non c'è motivo di usare malloc in questo caso, quindi non devi preoccuparti di liberare.

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