2009-12-01 19 views
8
#include <stdio.h> 
#include <stdlib.h> 

void 
getstr(char *&retstr) 
{ 
char *tmp = (char *)malloc(25); 
strcpy(tmp, "hello,world"); 
retstr = tmp; 
} 

int 
main(void) 
{ 
char *retstr; 

getstr(retstr); 
printf("%s\n", retstr); 

return 0; 
} 

gcc no compilaría este archivo, pero después de agregar #include <cstring> podría usar g ++ para compilar este archivo fuente.Pasando el argumento del puntero por referencia bajo C?

El problema es: ¿el lenguaje de programación C admite el paso del argumento del puntero por referencia? Si no, ¿por qué?

Gracias.

+0

No está relacionado con su pregunta, pero por curiosidad, ¿cuál es el caso de uso para pasar un puntero como referencia? –

+1

@Tristram: si desea que la función pueda modificar el puntero, y hacer que la modificación se propague más allá del alcance de la función. –

+0

Si desea realizar un malloc de cadenas en una función que no libera esa memoria, podría considerar usar valgrind o una herramienta equivalente para detectar fugas de memoria. –

Respuesta

29

No, C no admite referencias. Es por diseño. En lugar de referencias, puede usar el puntero al puntero en C. Las referencias están disponibles solo en lenguaje C++.

5

Prueba esto:


void 
getstr(char **retstr) 
{ 
char *tmp = (char *)malloc(25); 
strcpy(tmp, "hello,world"); 
*retstr = tmp; 
} 

int 
main(void) 
{ 
char *retstr; 

getstr(&retstr); 
printf("%s\n", retstr); 

return 0; 
} 
+1

No arroje el valor de retorno de 'malloc'. Puede ocultar un error al '#include ' (que olvidó en el código anterior). Consulte http://c-faq.com/malloc/mallocnocast.html Además, no se olvide de verificar el valor de retorno de 'malloc'. –

+3

¡Guau, algunas personas luchan por ver la diferencia entre una rutina de prueba de prueba de concepto y un código de producción! Era obvio que esta era una rutina de prueba aproximada porque no había un "libre" correspondiente, pero creo que algunas personas olvidan lo obvio. –

20

Las referencias son una característica de C++, C, mientras que sólo admite punteros. Para que su función de modificar el valor del puntero, dados, pasar el puntero al puntero:

void getstr(char ** retstr) 
{ 
    char *tmp = (char *)malloc(25); 
    strcpy(tmp, "hello,world"); 
    *retstr = tmp; 
} 

int main(void) 
{ 
    char *retstr; 

    getstr(&retstr); 
    printf("%s\n", retstr); 

    // Don't forget to free the malloc'd memory 
    free(retstr); 

    return 0; 
} 
+2

No eche lo que 'malloc()' devuelve. Si ha incluido 'stdlib.h', no hace absolutamente nada. Si no lo has hecho, oculta ese hecho. –

+3

Como 'malloc' devuelve' void * 'Me parece una buena práctica convertirlo explícitamente al tipo requerido en lugar de depender de las conversiones implícitas. Si 'stdlib.h' no está incluido, el casting no oculta ese hecho: el compilador le advertirá que' malloc' no ha sido declarado. –

0

C Lang no tiene variables de referencia, pero su parte de C++ lang.

El motivo de la introducción de referencia es evitar punteros colgantes y la comprobación previa de la nulidad de los punteros.

Puede considerar la referencia como puntero constante es decir, el puntero const solo puede señalar a los datos que se ha inicializado al punto.

+0

La otra diferencia (además de las sintácticas) es que las referencias no pueden ser nulas. –

2

Esto debería ser un comentario pero es demasiado largo para un cuadro de comentarios, así que lo estoy haciendo CW.

El código que ya ha proporcionado puede ser mejor escribir como:

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

void 
getstr(char **retstr) 
{ 
    *retstr = malloc(25); 
    if (*retstr) { 
     strcpy(*retstr, "hello,world"); 
    } 
    return; 
} 

int 
main(void) 
{ 
    char *retstr; 

    getstr(&retstr); 
    if (retstr) { 
     printf("%s\n", retstr); 
    } 
    return 0; 
} 
1

Hay un truco interesante en libgmp que emula referencias: typedef mpz_t __mpz_struct[1];

y luego se puede escribir así:

mpz_t n; 
mpz_init(n); 
... 
mpz_clear(n); 

No recomendaría usar este método, porque puede ser incomprensible para otros, aún así no protege de ser a NULL: mpz_init((void *)NULL), y es tan detallado como su contraparte de puntero a puntero.

Cuestiones relacionadas