IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Pointeur et passage par adresse


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Par défaut Pointeur et passage par adresse
    Bonjour,

    j'ai besoin de vos lumières, ça fait un bail que j'ai pas touché les pointeurs

    je cherche la façon la plus propre.

    j'ai le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>
    void traitement (char* buf, int* size)
    {
      char *texte = "test";
     *size = 6;
      *buf = texte !!!!!!!!
    }
    int main ()
    {
     int valeur = 4;
     char* buffer=NULL;
     clrscr();
     traitement (buffer,&valeur);
     printf ("\nsize = %d",valeur);
     printf ("\nbuffer = %s",buffer);
     return 1;
    }
    Question : je veux affecter à la variable buf dans la fonction traitement la valeur de la variable texte ???? comment faire et la façon la plus propre, car dans ma fonction main je veux exploiter ces deux variables

    merci,

    Cordialement,

    Turbo_chess

  2. #2
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Salut,

    Si, je prends ta question au pied de la lettre, ce que tu veux faire c'est "buf = texte", mais c'est pas ce que tu veux faire.

    Quand on veut creer une chaine, il faut se demander où on va stoquer les caractères la constituant. Il ne faut pas croire que les variables de type "char *" sont des objets de type chaine comme dans les technologies de plus haut niveau.
    Ainsi, il faut d'une manière ou d'une autre, avoir un tableau de caractère avec une taille suffisante pour y mettre les caractères constituant la nouvelle chaine. Un moyen simple est de faire une variable tableau de caractère de taille fixe. Attention à la duree de vie des variables locales automatiques car elles ne sont valides que dans le scope (le bloc d'accolades) où elles sont declarées.
    Je te laisse cogiter tout ça et proposer quelquechose.

  3. #3
    Membre confirmé
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Par défaut
    Citation Envoyé par Gruik Voir le message
    Salut,

    Si, je prends ta question au pied de la lettre, ce que tu veux faire c'est "buf = texte", mais c'est pas ce que tu veux faire.

    Quand on veut creer une chaine, il faut se demander où on va stoquer les caractères la constituant. Il ne faut pas croire que les variables de type "char *" sont des objets de type chaine comme dans les technologies de plus haut niveau.
    Ainsi, il faut d'une manière ou d'une autre, avoir un tableau de caractère avec une taille suffisante pour y mettre les caractères constituant la nouvelle chaine. Un moyen simple est de faire une variable tableau de caractère de taille fixe. Attention à la duree de vie des variables locales automatiques car elles ne sont valides que dans le scope (le bloc d'accolades) où elles sont declarées.
    Je te laisse cogiter tout ça et proposer quelquechose.
    merci je sais déjà ça, mais je cherche la façon la plus propre, l'allocation est primordial, j'ai pas complété l'exemple, je m'excuse , mais c'est le but de ma question

    merci

  4. #4
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Par défaut
    strdup() ne fait pas partie de la norme C bien que proposée par la plupart des implémentations de la lib C
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  5. #5
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Rq: tu ne peux pas !
    Rq2: pourquoi 6 et non 5 (comme le fait le code suivant) ??

    Perso:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    void traitement (char**buf, int* size)
    {
    #    define TEXT "test"
        *size = sizeof(TEXT);
        *buf = TEXT;
        return; 
    }
    int main (void)
    {
        int valeur = 4;
        char* buffer=NULL;
    #   if je_sais_pas_quoi
        clrscr();
    #   endif
        traitement (&buffer,&valeur); /* pointer sur buffer */
        printf ("\nsize = %d",valeur);
        printf ("\nbuffer = %s",buffer);
        return 0; /* 0 == ok */
    }
    Edit:
    d'après Gruik ça ne marche pas (et je suis trop feignant pour chercher dans la norme, mais en es-tu sur (Gruik) ?), donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    void traitement (char**buf, int* size)
    {
    #    define TEXT "test"
        *size = sizeof(TEXT);
        *buf = strdup(TEXT)
        return; 
    }
    int main (void)
    {
        int valeur = 4;
        char* buffer=NULL;
    #   if je_sais_pas_quoi
        clrscr();
    #   endif
        traitement (&buffer,&valeur); /* pointer sur buffer */
        if (buffer) {
            printf ("\nsize = %d",valeur);
            printf ("\nbuffer = %s",buffer);
            free(buffer);
        }
        return 0; /* 0 == ok */
    }

  6. #6
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Ok, c'est parti


    Version 1.1 : traitement() retourne un pointeur sur une chaine litterale et on a la taille du tableau de caractère qui la contient via le paramètre en mise à jour "size"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    #include <stdio.h>
    #include <string.h> /* size_t */
     
    const char * traitement(size_t /* type naturel des tailles en nb de bytes */ * size)
    {
        *size = sizeof("test");
        return "test";
    }
     
    int main (void)
    {
        size_t taille = 4;
        const char * s = NULL;
     
        s = traitement(&valeur);
        printf ("size = %zu\n", taille);
        printf ("string = %s\n", s);
        return 0;
    }

    Version 1.2 : même chose mais on voulait la longueur de la chaine (ce qui est quand meme plus utile semantiquement parlant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include <stdio.h>
     
    const char * traitement(unsigned * lg)
    {
        *lg = sizeof("test") - 1;
        return "test";
    }
     
    int main (void)
    {
        unsigned longueur = 4;
        const char * s = NULL;
     
        s = traitement(&longueur);
        printf ("longueur = %u\n", longueur);
        printf ("string = %s\n", s);
        return 0;
    }
    Version 2.1 : traitment() ecrit les caractère de le nouvelle chaine dans un tableau géré par l'appellant (c'est le plus courant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    #include <stdio.h>
     
    /* Ecrit la nouvelle chaine dans out. Mets dans *lg_out sa longueur.
        Retourne out (pour information, ceci permet d'utiliser la chaine ecrite dans out en paramètre d'une autre fonction, comme un *printf() -- c'est ce que fait strcpy par exemple)  */
    char * traitement(char * out, unsigned * lg_out)
    {
        unsigned lg;
        lg = sizeof("test") - 1;
        *lg_out = lg;
        return strcpy(out, "test");
    }
     
    int main (void)
    {
        unsigned longueur;
        char buffer[50];
     
        traitement(buffer, &longueur);
        printf ("longueur = %u\n", longueur);
        printf ("buffer = %s\n", buffer);
        return 0;
    }
    Version 2.2 : meme chose mais avec protection contre les depassements.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #include <stdio.h>
    #include <string.h> /* size_t, memcpy() */
     
    #define MIN(a, b) ((a) < (b) ? (a) : (b))
     
    /* out_size doit être la taille du tableau de caractères pointé par out en nombre de bytes */
    char * traitement(char * out, size_t out_size, unsigned * lg_out)
    {
        unsigned lg;
        lg = MIN(sizeof("test") - 1, out_size - 1);
        memcpy(out, "test", lg);
        out[lg] = '\0';
        *lg_out = lg;
        return out;
    }
     
    int main (void)
    {
        unsigned longueur;
        char buffer[50];
        char buffer2[4];
     
        traitement(buffer, sizeof buffer, &longueur);
        printf ("longueur = %u\n", longueur);
        printf ("buffer = %s\n", buffer);
     
        traitement(buffer2, sizeof buffer2, &longueur);
        printf ("longueur = %u\n", longueur);
        printf ("buffer = %s\n", buffer2);
        return 0;
    }

    Version 3 : allocation d'un nouveau tableau de caractères par traitement() et liberation par l'appellant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    #include <stdio.h>
    #include <stdlib.h> /* malloc, ... */
    #include <string.h> /* size_t, memcpy(), strdup() */
     
    char * traitement(unsigned * lg_out)
    {
        char * new_s;
        unsigned lg;
        lg = sizeof("test") - 1;
     
        #if C_ANSI_89_POUET_POUET
             new_s = malloc(lg + 1);
             strcpy(new_s, "test");
        #else
             new_s = strdup("test");
        #endif
        *lg_out = lg;
        return new_s;
    }
     
    int main (void)
    {
        unsigned longueur;
        char * s;
     
        s = traitement(&longueur);
        printf ("longueur = %u\n", longueur);
        printf ("string = %s\n", s);
        free(s), s = NULL;
     
        return 0;
    }

  7. #7
    Membre confirmé
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Par défaut
    Bonjour,

    merci pour vos réponses.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    #include <stdio.h>
    void traitement (char* strBuffer, int * strLength)
    {
       int longeur = 4;
      *strLength= longeur;
       memcpy (strBuffer,"test",4);
    }
    int main ()
    {
     char *buffer= (char*) malloc (4);
     int longeur = 0;
     traitement (buffer,&longeur);
     printf ("\nsize = %d",longeur);
     printf ("\nbuffer = %s",buffer);
     printf ("\nlongeur = %d",strlen(buffer));
     free (buffer);
     buffer = NULL;
     return 1;
    }
    merci,

    Cordialement,

    Turbo_chess

  8. #8
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Attention, comportement indéterminé ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("\nbuffer = %s",buffer);
    En effet, buffer ne pointe pas sur une chaine valide car le tableau sur lequel il pointe ne contient pas de \0 final -> tout peut arriver.

    Quand on veut creer une nouvelle chaine, il faut avoir un tableau de caractères avec pour nombre de bytes, la longueur max de ce qu'on veut y mettre +1.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <stdio.h>
    void traitement (char* strBuffer, int * strLength)
    {
       int longeur = 4;
      *strLength= longeur;
       memcpy (strBuffer,"test",4);
       strBuffer[longueur] = '\0';
       /* ou encore : strcpy(buffer, "test"); */
    }
    int main ()
    {
     char *buffer= (char*) malloc (4 + 1);
     int longeur = 0;
     traitement (buffer,&longeur);
     printf ("\nsize = %d",longeur);
     printf ("\nbuffer = %s",buffer);
     printf ("\nlongeur = %d",strlen(buffer));
     free (buffer);
     buffer = NULL;
     return 1;
    }

  9. #9
    Membre confirmé
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Par défaut
    Citation Envoyé par Gruik Voir le message
    Attention, comportement indéterminé ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("\nbuffer = %s",buffer);
    En effet, buffer ne pointe pas sur une chaine valide car le tableau sur lequel il pointe ne contient pas de \0 final -> tout peut arriver.

    Quand on veut creer une nouvelle chaine, il faut avoir un tableau de caractères avec pour nombre de bytes, la longueur max de ce qu'on veut y mettre +1.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <stdio.h>
    void traitement (char* strBuffer, int * strLength)
    {
       int longeur = 4;
      *strLength= longeur;
       memcpy (strBuffer,"test",4);
       strBuffer[longueur] = '\0';
       /* ou encore : strcpy(buffer, "test"); */
    }
    int main ()
    {
     char *buffer= (char*) malloc (4 + 1);
     int longeur = 0;
     traitement (buffer,&longeur);
     printf ("\nsize = %d",longeur);
     printf ("\nbuffer = %s",buffer);
     printf ("\nlongeur = %d",strlen(buffer));
     free (buffer);
     buffer = NULL;
     return 1;
    }
    Bonjour,

    merci Gruik. tu as tout à fait raison.

    une question , si j'exploite le buffer en tant que zone mémoire , est ce que je suis obligé d'utiliser strBuffer[longueur] = '\0'; ???

    merci,

    Cordialement,

    Turbo_chess

  10. #10
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Gruik Voir le message
    Attention, comportement indéterminé ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("\nbuffer = %s",buffer);
    En effet, buffer ne pointe pas sur une chaine valide car le tableau sur lequel il pointe ne contient pas de \0 final -> tout peut arriver.

    Quand on veut creer une nouvelle chaine, il faut avoir un tableau de caractères avec pour nombre de bytes, la longueur max de ce qu'on veut y mettre +1.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <stdio.h>
    void traitement (char* strBuffer, int * strLength)
    {
       int longeur = 4;
      *strLength= longeur;
       memcpy (strBuffer,"test",4);
       strBuffer[longueur] = '\0';
       /* ou encore : strcpy(buffer, "test"); */
    }
    int main ()
    {
     char *buffer= (char*) malloc (4 + 1);
     int longeur = 0;
     traitement (buffer,&longeur);
     printf ("\nsize = %d",longeur);
     printf ("\nbuffer = %s",buffer);
     printf ("\nlongeur = %d",strlen(buffer));
     free (buffer);
     buffer = NULL;
     return 1;
    }
    J'ai l'impression que le problème est posé à l'envers ici. En effet, si c'est main() qui est responsable de l'allocation de mémoire, l'interface de la fonction traitement doit être:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void traitement(char *strBuffer, size_t bufLength);
    où bufLength est la longueur du tampon passé à en 1er argument.

    L'exemple que tu proposes présente à mon avis de gros problèmes de conception (pourquoi la fonction traitement est-elle autorisée à modifier la valeur pointée par strLength?), et n'est pas très robuste (au minimum, vérifier que l'allocation dynamique de mémoire s'est bien passée et que la chaîne copie dans strBuffer ne va pas entraîner un débordement de tampon).

    Par ailleurs, pourquoi main() retourne-t'elle la valeur 1 lors d'une exécution avec succès. La convention veut qu'elle retourne 0 ou EXIT_SUCCESS dans ce cas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define BUF_LENGTH 10
     
    void traitement (char* strBuffer, size_t bufLength)
    {
        if (strBuffer != NULL && bufLength > 0)
        {
            char const *mot = "test";
     
            /* On copie mot dans le tampon, on s'assure d'ajouter le caractère nul
               fin de chaine et on se protège contre un éventuel débordement de
               tampon
            */
            *strBuffer = 0;
            strncat(strBuffer, mot, bufLength - 1);
        }
    }
     
    int main (void)
    {
        int err = EXIT_SUCCESS;
     
        /*-TC- Le cast de malloc() n'est pas necessaire et même deonseille' */
        char *buffer = malloc (BUF_LENGTH * sizeof *buffer);
        /* -TC- toujours verifier la valeur retournee par *alloc() */
        if (buffer != NULL)
        {
            traitement (buffer, BUF_LENGTH);
            printf ("buffer = %s\n", buffer);
            printf ("longeur = %u\n",(unsigned int) strlen(buffer));
     
            free (buffer);
            buffer = NULL;
        }
        else
        {
            fprintf(stderr, "Impossible to allocate memory!\n");
            err = EXIT_FAILURE;
        }
     
        return err;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passage par adresse d'un triple pointeur
    Par garbage.collector dans le forum C++
    Réponses: 6
    Dernier message: 14/11/2013, 16h55
  2. Réponses: 12
    Dernier message: 26/01/2008, 21h23
  3. Passage par valeur / passage par adresse
    Par jeje99 dans le forum C++
    Réponses: 13
    Dernier message: 16/02/2006, 11h29
  4. passage par adresse
    Par cari dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 01/02/2006, 12h33
  5. [Debutant(e)]passage par adresse?
    Par cap2fosse dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2004, 11h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo