8
votes

Argument de pointeur de passage par référence sous C?

#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 would not compile this file, but after adding #include <cstring> I could use g++ to compile this source file.The problem is: does the C programming language support passing pointer argument by reference? If not, why?Thanks.

5 commentaires

Non liée à votre question, mais pour la curiosité, quel est le cas d'utilisation pour passer un pointeur comme référence?


@TRistram: Si vous souhaitez que la fonction puisse modifier le pointeur et que la modification se propage au-delà du cadre de la fonction.


Si vous souhaitez effectuer MALLOC de chaînes dans une fonction qui ne libère pas cette mémoire, vous pouvez envisager d'utiliser Valgrind ou un outil équivalent pour tester les fuites de mémoire.


Une référence est une façon de confondre des programmeurs quant à ce qui se passe vraiment. Si vous discipliez votre approche des indicateurs, vous constaterez que les références ne sont pas nécessaires. Lorsque vous traitez avec une référence, un compilateur prend des mesures sur un objet et la gestion de l'indirection pour vous.


Pp: simplification excessive des références; Toute caractéristique peut être abusée.


6 Réponses :


29
votes

Non, c ne prend pas en charge les références. C'est par conception. Au lieu de références, vous pouvez utiliser le pointeur vers le pointeur dans C. Les références sont disponibles uniquement dans la langue C ++.


0 commentaires

5
votes

Essayez ceci:

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


2 commentaires

Ne pas jeter la valeur de retour du MALLOC . Il peut cacher une défaillance de #include (que vous avez oublié dans le code ci-dessus). Voir C-FAQ.com/malloc/mallocnocast.html également, n'oubliez pas Pour vérifier la valeur de retour de malloc .


Wow, certaines personnes ont du mal à voir la différence entre une preuve de la routine de test de concept et du code de production! Il était évident que c'était une routine d'essai approximative et prête, car il n'y avait pas de correspondant mais je suppose que certaines personnes manquent l'évidence!



20
votes

Les références sont une fonctionnalité de C ++, tandis que C ne prend en charge que les pointeurs. Pour que votre fonction modifie la valeur du pointeur donné, passez le pointeur sur le pointeur:

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 commentaires

Ne pas lancer ce que malloc () retourne. Si vous avez inclus stdlib.h , il ne fait absolument rien. Si vous ne l'avez pas fait, cela cache ce fait.


Comme MALLOC renvoie vide * Je trouve la bonne pratique de la jeter explicitement au type requis au lieu de s'appuyer sur des conversions implicites. Si stdlib.h n'est pas inclus, la coulée ne cache pas ce fait - le compilateur vous avertira que malloc n'a pas été déclaré.



0
votes

C Lang n'a pas de variables de référence mais sa partie de C ++ Lang.

Le motif d'introduction de la référence consiste à éviter les pointeurs suspendus et pré-vérification des pointeurs nullité.

Vous pouvez envisager de vous référer comme Pointeur constant I.E. CONSTER POINTER ne peut indiquer que des données qu'il a été initialisée au point.


1 commentaires

L'autre différence (en plus des syntaxes) est que les références ne peuvent pas être nuls.



2
votes

Cela devrait être un commentaire, mais il est trop long pour une boîte de commentaire, donc je le fais cw.

Le code que vous avez fourni peut être mieux écrit comme suit: P>

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


0 commentaires

1
votes

Il y a une astuce intéressante dans Libgmp qui émule des références: Typedef mpz_t __mpz_truct [1];

et ensuite vous pouvez écrire comme ceci: xxx

Je ne recommanderais pas d'utiliser cette méthode, car Il peut être incompréhensible pour les autres, il ne protège toujours pas d'être un null: mpz_init ((vide *) null) , et c'est autant verbeux que son homologue pointeur à pointeur.


0 commentaires