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 :

Comment initialiser un pointeur ?


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 135
    Points : 67
    Points
    67
    Par défaut Comment initialiser un pointeur ?
    Salut à tous :-)

    Bon voilà, je veux écrire une fonction en C qui reçoit un pointeur de type int et l’initialise :
    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 <stdlib.h>
     
    int init(int* x) {
        x = (int*) malloc(sizeof (int));
        if (x == NULL) return 0;
        else {
            *x = 90;
            return 1;
        }
    }
     
    int main() {
        int *r;
        init(r);
        if (!init(r)) printf("Memoire insufisante");
        else
            printf("%d", *r);
        return 0;
    }
    Mais le problème c'est que le programme plante lors de l'exécution.
    Où est-il le Bug ?

    Merci d'avance.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Je t'invite à regarder cette discussion où IsraGab a rencontré le même problème. Avec en particulier les messages #5 et #7.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 135
    Points : 67
    Points
    67
    Par défaut
    Merci beaucoup de m'avoir répondu si rapidement.
    En ce qui concerne le lien, je vois que le problème de IsraGab été avec la copie du string au lieu de l'affectation directe et je parle pas de cela :-)

    D'autre part, j'ai remarqué que la fonction marche si on lui passe la référence du pointeur :
    int init(int* &x) {
    ...
    }
    Qu'en vous pensez ?

  4. #4
    Invité
    Invité(e)
    Par défaut
    Non tu ne parles pas de string mais de pointeur sur int, mais le principe est exactement le même que celui expliqué dans les messages vers lesquels je t'ai dirigé.
    À savoir que tu manipules au sein de ta fonction init() une copie du pointeur original r. Autrement-dit une assignation du type x = ... n'aura aucune influence sur r contrairement à *x = ... qui modifiera bien le contenu pointé. Il faut ainsi utiliser un pointeur de pointeur pour effectivement répercuter le changement imposé par malloc().

    L'utilisation de la référence est correcte, sauf que (comme aussi indiqué dans la discussion...) c'est du C++ et non du C.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 135
    Points : 67
    Points
    67
    Par défaut
    À savoir que tu manipules au sein de ta fonction init() une copie du pointeur original
    Mais si on passe un pointeur d'une variable, alors les modifications effectués sur la copie seront aussi effectuer sur l'originale, car l'adresse du variable est "unique", n'est-ce pas ?
    Donc pourquoi a-t-on besoin de passer un pointeur de pointeur ?

    L'utilisation de la référence est correcte, sauf que c'est du C++ et non du C.
    Et si je veux écrire un Code C "pure", Que dois-je faire ?

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par khaled_prg Voir le message
    Mais si on passe un pointeur d'une variable, alors les modifications effectués sur la copie seront aussi effectuer sur l'originale, car l'adresse du variable est "unique", n'est-ce pas ?
    Donc pourquoi a-t-on besoin de passer un pointeur de pointeur ?
    Un pointeur est aussi une variable. Si tu souhaites modifier l'objet vers lequel il pointe, il faut modifier sa valeur et donc passer par un pointeur.
    D'où l'utilisation de pointeurs de pointeur.

    Citation Envoyé par khaled_prg Voir le message
    Et si je veux écrire un Code C "pure", Que dois-je faire ?
    En C, on utilise des pointeurs constants à la place de références.

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 135
    Points : 67
    Points
    67
    Par défaut
    Un pointeur est aussi une variable. Si tu souhaites modifier l'objet vers lequel il pointe, il faut modifier sa valeur et donc passer par un pointeur.
    D'où l'utilisation de pointeurs de pointeur.
    J'ai bien compris l'idée, c'est claire.
    Merci.

    En C, on utilise des pointeurs constants à la place de références.
    Mais si le pointeur (passé en paramètre) ne sera pas "constant", aura-t-il une confusion ?

  8. #8
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Quand une fonction prend un paramètre en constant (ex : const int) ceci ne signifie pas grand chose pour l'utilisateur car le paramètre sera passé par copie, donc tu peux lui transmettre un paramètre constant ou non.

    Par contre dans le cas où tu met en paramètre un const int * ptr donc un pointeur sur un objet "considéré comme constant".
    C'est à dire que tu ne pourras pas modifier l'objet pointé via ce pointeur. ( Ce qui n'est pas tout à fait vrai en C ).
    Dans ce cas là tu pourras lui transmettre int * ptr; ou
    const int * ptr;.
    Par contre pour une fonction prenant un int * ptr tu ne devrait pas pouvoir lui donner un const int * ptr;.

    A ne pas confondre avec un pointeur constant qui ne peut pas modifier sa valeur : int * const ptr

  9. #9
    Membre éclairé
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Points : 807
    Points
    807
    Par défaut
    Citation Envoyé par khaled_prg Voir le message
    Mais si le pointeur (passé en paramètre) ne sera pas "constant", aura-t-il une confusion ?
    Tu peux utiliser un pointeur de type T quand un pointeur de type const T est attendu (mais pas l'inverse, évidemment). Il y a bien l'exception bien connue de la conversion T** vers const T** qui n'est pas implicite du fait de la non-récursivité de cette règle, mais la solution est alors de passer par un transtypage malpropre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /* L'Exception qui confirme la règle */
    void f(const int **p) { /* ... */ }
     
    int main(void) {
    	int *x;
    	f((const int **)&x);
    	return 0;
    }
    Récursivité en C : épidémie ou hérésie ?

    "Pour être un saint dans l'Église de l'Emacs, il faut vivre une vie pure. Il faut se passer de tout logiciel propriétaire. Heureusement, être célibataire n'est pas obligé. C'est donc bien mieux que les autres églises" - Richard Stallman

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 135
    Points : 67
    Points
    67
    Par défaut
    Je m'excuse du retard :-(
    Je vous remercie vivement pour l'intérêt que vous avez porté à cette discussion.

    => Résolu.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Kirilenko Voir le message
    Il y a bien l'exception bien connue de la conversion T** vers const T** qui n'est pas implicite du fait de la non-récursivité de cette règle, mais la solution est alors de passer par un transtypage malpropre.
    Correction, c'est la conversion T** vers const T * const * qui est correcte mais nécessite un transtypage en C (elle est d'ailleurs acceptée en C++).

    La conversion T** vers const T** est toujours malpropre et doit être évitée.

    En effet, elle permet de convertir silencieusement un pointeur const en pointeur non-const! Exemple:
    Code C : 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
    int GetString(char const **ps, int num)
    {
    	char const * sret; /*Notez que ce pointeur est const*/
    	switch(num)
    	{
    	case 1: sret = "toto"; break;
    	case 2: sret = "tata"; break;
    	default: sret = NULL; break;
    	}
     
    	*ps = sret;
    	return (sret==NULL ? 0 : strlen(sret));
    }
     
    int main(void)
    {
    	/*Code correct*/
    	{
    		char const *s;
    		int len = GetString(&s, 1);
    		puts(s);
    	}
    	/*Code faux*/
    	{
    		char *s;
    		int len = GetString((char const **)&s, 1); /*On place sret dans un pointeur non-const!*/
    		s[0] = 'A'; /*BOUM.*/
    	}
    	return 0;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre éclairé
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Points : 807
    Points
    807
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Correction, c'est la conversion T** vers const T * const * qui est correcte mais nécessite un transtypage en C (elle est d'ailleurs acceptée en C++).

    La conversion T** vers const T** est toujours malpropre et doit être évitée.

    En effet, elle permet de convertir silencieusement un pointeur const en pointeur non-const! Exemple:
    Code C : 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
    int GetString(char const **ps, int num)
    {
    	char const * sret; /*Notez que ce pointeur est const*/
    	switch(num)
    	{
    	case 1: sret = "toto"; break;
    	case 2: sret = "tata"; break;
    	default: sret = NULL; break;
    	}
     
    	*ps = sret;
    	return (sret==NULL ? 0 : strlen(sret));
    }
     
    int main(void)
    {
    	/*Code correct*/
    	{
    		char const *s;
    		int len = GetString(&s, 1);
    		puts(s);
    	}
    	/*Code faux*/
    	{
    		char *s;
    		int len = GetString((char const **)&s, 1); /*On place sret dans un pointeur non-const!*/
    		s[0] = 'A'; /*BOUM.*/
    	}
    	return 0;
    }
    Au temps pour moi, je me suis emmêlé les pinceaux avec le transtypage (qui, lui, est bien const t **, du fait de l'inutilité de la qualification du pointeur constant dans ce cas).
    Récursivité en C : épidémie ou hérésie ?

    "Pour être un saint dans l'Église de l'Emacs, il faut vivre une vie pure. Il faut se passer de tout logiciel propriétaire. Heureusement, être célibataire n'est pas obligé. C'est donc bien mieux que les autres églises" - Richard Stallman

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

Discussions similaires

  1. Réponses: 14
    Dernier message: 19/06/2014, 10h33
  2. Comment initialiser une ChildFrame ???
    Par loupdeau dans le forum MFC
    Réponses: 14
    Dernier message: 22/03/2005, 13h28
  3. Réponses: 4
    Dernier message: 08/02/2005, 20h47
  4. Comment initialiser un vector à sa création ?
    Par Clad3 dans le forum SL & STL
    Réponses: 7
    Dernier message: 10/12/2004, 15h01
  5. Initialisation de pointeurs
    Par Gnux dans le forum C
    Réponses: 5
    Dernier message: 03/10/2003, 17h10

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