Partage
  • Partager sur Facebook
  • Partager sur Twitter

Chaines de caractères et pointeurs

Quelques trucs qui m'échappent

Sujet résolu
    4 septembre 2007 à 13:36:03

    Salut !
    V'la, j'ai 2,3 p'tites questions et quelques exemples où j'ai besoin d'explication.
    Voici un mini prog :

    1. #include <iostream>
    2. using namespace std;
    3. int main(int argc, char *argv[])
    4. {
    5.     char *pointeur = NULL;
    6.     char tableau[50];
    7.     cin >> pointeur; // Plantage
    8.     cout << pointeur;
    9.     cin >> tableau; // ok
    10.     cout << tableau;
    11.     /****** AUTRE TEST ******/
    12.     char *pointeur = "salut";
    13.     char tableau[] = "salut";
    14.     for (int i = 0; i < 5; i++)
    15.     {
    16.         pointeur[i] = 'A'; // Plante
    17.         tableau[i] = 'A'; // Ok
    18.     }
    19.     cout << pointeur << endl << tableau << endl;
    20.     system ("PAUSE");
    21.     return 0;
    22. }


    C'est pas la première fois que je remarque certains différences entre pointeur vers char et tableau de char. Quelqu'un peut m'expliquer pourquoi ca plante ? Dans quel cas utilisez un tableau ou un pointeur ?


    Merci d'avance :)
    • Partager sur Facebook
    • Partager sur Twitter
      4 septembre 2007 à 13:42:15

      http://developpez.net et regarde dans la FAQ, cette question revient presque chaque semaine.

      Sinon une remarque personelle: N'utilise pas de char* en C++, il y a des <string> pour ça !
      • Partager sur Facebook
      • Partager sur Twitter
      Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
        4 septembre 2007 à 13:56:52

        Ce lien m'ammène sur le forum. Tu veux que je cherche dans les topics des forums ou dans le FAQ sur le C++ ?

        J'ai cherché dans les 2, sans succès :(
        • Partager sur Facebook
        • Partager sur Twitter
          4 septembre 2007 à 14:20:39

          Ok, alors je vais répondre rapidement. Un pointeur n'est pas un tableau. (A quoi bon avoir deux trucs différents pour la même chose?)

          MAIS, il se trouve que on peut "associer" un pointeur à un tableau (cette formulation ne me plaît pas) de telle sorte qu'il pointe sur la première "case" d'un tableau.

          En ce qui concerne ton premier plantage, c'est autre chose, le pointeur pointeur contient une adresse mémoire. Tu ne peux pas lui mettre le résultat d'un cin à l'intérieur.

          Pour ta deuxième erreur, pointeur n'est pas un tableau, tu ne peux donc pas utiliser les []. Par contre ceci fonctionne:
          1. for (int i = 0; i < 5; i++){
          2. *(pointeur +i)  = 'A';
          3. }


          a+
          • Partager sur Facebook
          • Partager sur Twitter
          Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
            4 septembre 2007 à 14:54:54

            Nanoc > je ne suis pas d'accord :
            Il pourrait tres bien utiliser pointeur[i];
            c'est la meme chose que *(pointeur+i);

            Ce qu'il faut bien voir, c'est au niveau de l'allocation :
            Quand tu parles de "tableau", tu parles d'une adresse (comme un pointeur) mais a un endroit ou la mémoire a été allouée :

            Quand tu fais :
            char tableau[50]; --> tableau est une adresse, ET a cette adresse sont alloués 50 char.

            Alors que quand tu fais :
            char* pointeur = NULL;

            le "pointeur" contient une adresse, mais avec rien d'allouer a cet endroit -> donc si tu essaies de lire ou d'écrire a cet endroit, ça plante !

            Pour résoudre cela, il faut allouer ton pointeur :

            char* pointeur = NULL;
            pointeur = new char[50]; // la c'est alloué.

            Et ton programme marchera.
            Par contre, a la fin, n'oublie pas :

            delete [] pointeur;
            • Partager sur Facebook
            • Partager sur Twitter

            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

              4 septembre 2007 à 15:12:47

              Les tableaux en C++ sont des références (&) :
              Aloués lors de leur déclaration.
              Désaloués automatiquement à la fin du bloc.
              Pas besoin de "*" ou de "->" pour rediriger vers la valeur.
              • Partager sur Facebook
              • Partager sur Twitter
                4 septembre 2007 à 16:07:30

                Alors, c'est plus clair MAIS :
                Quand je fais :
                1. char *pointeur = "salut"; // Ok
                2. for (int i = 0; i < 5; i++)
                3.     {
                4.         pointeur[i] = 'A'; // Plante
                5.     }


                Pourtant, après que j'ai fais ça : char *pointeur = "salut", il y a bien eu une 6 p'tites cases réservées pour mon pointeur ? Donc, si je tente de les modifier, ca devrait pas planter ?

                Second truc :

                1. char *pointeur = NULL;
                2. cin >> pointeur;

                La 1ere ligne s'alloue une case en mémoire. Donc logiquement, si, dans le cin, je ne mets qu'un seul caractère, ca devrait pas planter (puisque char occupe 1 seule case) ?

                Dernier truc :
                P'tit code issu du cours de mat :
                1. // Prototype de la fonction d'affichage
                2. void affiche(long *tableau, long tailleTableau);
                3. int main(int argc, char *argv[])
                4. {
                5.     long tableau[4] = {10, 15, 3}, i = 0;
                6.     // On affiche le contenu du tableau
                7.     affiche(tableau, 4);
                8.     return 0;
                9. }
                10. void affiche(long *tableau, long tailleTableau)
                11. {
                12.     long i;
                13.     for (i = 0 ; i < tailleTableau ; i++)
                14.     {
                15.         printf("%ld\n", tableau[i]);
                16.     }
                17. }

                Ici, on accède bel et bien, via un pointeur, à plusieurs cases mémoires. Or, si j'ai bien compris, quand on appelle la fonction, on transmet l'adresse et uniquement une simple adresse (puisque tableau <=> &tableau[0]) au pointeur. Comment peut-il savoir jusqu'à quel adresse mémoire le pointeur peut-il aller ? Pourquoi ça plante pas ? Surtout que dans la fonction, le tableau crée dans main n'existe plus, donc la mémoire a été rendue.
                • Partager sur Facebook
                • Partager sur Twitter
                  4 septembre 2007 à 16:16:43

                  Pour la question 2:

                  Non, tu alloues rien, tu déclares un pointeur qui pourra pointer sur un char. Mais qui pour le moment ne pointe sur rien.

                  Et pour la 3:

                  C'est pour ça qu'on passe la taille du tableau en argument (le 2ème).
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                    4 septembre 2007 à 17:03:47

                    Citation : coyotte49

                    Alors, c'est plus clair MAIS :
                    Quand je fais :

                    1. char *pointeur = "salut"; // Ok
                    2. for (int i = 0; i < 5; i++)
                    3.     {
                    4.         pointeur[i] = 'A'; // Plante
                    5.     }



                    Pourtant, après que j'ai fais ça : char *pointeur = "salut", il y a bien eu une 6 p'tites cases réservées pour mon pointeur ? Donc, si je tente de les modifier, ca devrait pas planter ?



                    Non parce que salut c'est un const char : pas modifiable.

                    Citation : coyotte49

                    Second truc :

                    1. char *pointeur = NULL;
                    2. cin >> pointeur;


                    La 1ere ligne s'alloue une case en mémoire. Donc logiquement, si, dans le cin, je ne mets qu'un seul caractère, ca devrait pas planter (puisque char occupe 1 seule case) ?



                    Comme dit Nanoc ton pointeur n'est pas alloués. On alloue un pointeur avec new. En ce moment ton pointeur pointe sur l'adresse 0x0 soit une adresse invalide qui n'est pas allouable, lors d'un new l'espace nécessaire pour conserver ton type de variable/objet est réservée et l'adresse est retournée à ton pointeur.

                    Citation : coyotte49

                    Dernier truc :
                    P'tit code issu du cours de mat :

                    1. // Prototype de la fonction d'affichage
                    2. void affiche(long *tableau, long tailleTableau);
                    3. int main(int argc, char *argv[])
                    4. {
                    5.     long tableau[4] = {10, 15, 3}, i = 0;
                    6.     // On affiche le contenu du tableau
                    7.     affiche(tableau, 4);
                    8.     return 0;
                    9. }
                    10. void affiche(long *tableau, long tailleTableau)
                    11. {
                    12.     long i;
                    13.     for (i = 0 ; i < tailleTableau ; i++)
                    14.     {
                    15.         printf("%ld\n", tableau[i]);
                    16.     }
                    17. }


                    Ici, on accède bel et bien, via un pointeur, à plusieurs cases mémoires. Or, si j'ai bien compris, quand on appelle la fonction, on transmet l'adresse et uniquement une simple adresse (puisque tableau <=> &tableau[0]) au pointeur. Comment peut-il savoir jusqu'à quel adresse mémoire le pointeur peut-il aller ? Pourquoi ça plante pas ? Surtout que dans la fonction, le tableau crée dans main n'existe plus, donc la mémoire a été rendue.



                    Euh je crois que tu est un peu mélangé. Certe dans la fonction le tableau déclaré n'existe pas mais il existe encore dans main puisque main n'a pas terminé son bloc, il est seulement en attente. Comme il existe encore et qu'on passe le tableau en référence (je reviens à mon autre post, un tableau est une référence) on accède donc au même tableau que main.

                    Comment on ne dépasse pas du tableau ? simple tu as passé la taille du tableau à ta fonction qui a copié sa valeur dans tailleTableau.

                    Revois un peu le fonctionnement d'appel de fonction...
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 septembre 2007 à 17:52:56

                      D'ailleurs, précise ce que tu veux dire par "plante"

                      Quand tu modifies ton const char, ça doit etre une erreur de compilation qui survient, et non pas un plantage a l'execution ! Il faut bien nous préciser ça !
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                      Chaines de caractères et pointeurs

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown