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 de char**


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut Pointeur de char**
    Bonjour,

    Malgré mes recherches ("pointeur multi dimensionel") je ne parvient pas à résoudre mon probléme.
    J'ai réduit mon code au strict, comment le faire marcher ?

    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
    46
    47
    48
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(void)
    {
    	int i;
    	int j;
    	const char liste[3][11] = {
    		{"azertyuiop"},
    		 {"qsdfghjklm"},
    		  {"wxcvbn"}
    	};
    	char **ptr_3;
    	char *ptr_10;
     
    	// Marche (acces en tableau) :
    	/*
    	 * azertyuiop
    	 * qsdfghjklm
    	 * wxcvbn
    	 */
    	for (i = 0; i < 3; i++)
    	{
    		for (j = 0; j < 10; j++)
    		{
    			printf("%c", liste[i][j]);
    		}
    		printf("\n");
    	}
     
    	// Ne marche pas (acces en pointeur) :
    	ptr_3 = (char **)liste;
    	for (i = 0; i < 3; i++)
    	{
    		ptr_10 = *ptr_3;
    		// Plantage
    		for (j = 0; j < 10; j++)
    		{
    			printf("%c", *ptr_10); // Plantage
    			ptr_10++;
    		}
    		printf("\n");
    		ptr_3++;
    	}
     
    	return 0;
    }
    Merci beaucoup de vos réponses.

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

    Ton tableau liste est particulier, une ne passe pas de la première ligne à la seconde avec un simple ++ :
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    #define SHOW_ADDRESS(par) printf(#par ":%p\n", (void*)par)
     
    typedef char char_3[3];
     
    int main(void)
    {
        const char liste[3][11] = {
            {"azertyuiop"},
            {"qsdfghjklm"},
            {"wxcvbn"}
        };
     
        char **ptr = liste;
     
        SHOW_ADDRESS(&liste[0]);
        SHOW_ADDRESS(&liste[1]);
        SHOW_ADDRESS(&liste[2]);
        SHOW_ADDRESS(ptr + 0);
        SHOW_ADDRESS(ptr + 1);
        SHOW_ADDRESS(ptr + 2);
     
        return 0;
    }
    Ce qui se passe c'est que lorsqu'on passe aux double pointeur, on perd l'information de taille du tableau.
    Voici un code qui fait ce que tu attends :
    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
    46
    47
    48
    49
    50
    51
     
    #include <stdlib.h>
    #include <stdio.h>
     
    typedef char char_3[3];
     
    int main(void)
    {
        int i, j;
        char *ptr_10;
        char **ptr_3;
        const char liste[3][11] = {
            {"azertyuiop"},
            {"qsdfghjklm"},
            {"wxcvbn"}
        };
     
     
        /* méthode simple : on utilise encore liste[i]*/
    	for (i = 0; i < 3; i++)
    	{
    		ptr_10 = liste[i];
     
    		for (j = 0; j < 10; j++)
    		{
    			printf("%c", *ptr_10); 
    			ptr_10++;
    		}
    		printf("\n");
     
    	}
     
        /* méthode moins simple : on se décale de la taille de la premiere ligne
           du tableau */
    	ptr_3 = (char **)liste;
    	for (i = 0; i < 3; i++)
    	{
    		ptr_10 = ptr_3;
     
    		for (j = 0; j < 10; j++)
    		{
    			printf("%c", *ptr_10); 
    			ptr_10++;
    		}
    		printf("\n");
    		ptr_3 = (int)ptr_3 + sizeof *liste;
    	}
     
     
        return 0;
    }

  3. #3
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    je confirme l'incrément doit prendre en compte la taille des données du tableau.

    En simplifiant un peu, normalement le système va allouer un bloc de mémoire contiguë pour contenir ton tableau (3*10) 30 élément. ton tableau de 3x10 éléments sera considéré comme un tableau de 30 element par le système.

    l'adresse du premier élément de ton tableau est la même que celle de la première ligne. Cependant pour avoir l'adresse de la seconde ligne de ton tableau il faut faire un calcul et ajouter la taille mémoire de la première ligne afin de pointer sur le 11ème element du tableau.

    du fait de cette arrangement de la mémoire cette écriture:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    ptr_3 = (char **)liste;
    for (i = 0; i < 3; i++) {
     ptr_10 = ptr_3;
     for (j = 0; j < 10; j++) {
    	printf("%c", *ptr_10); 
    	ptr_10++;
     }
     printf("\n");
     ptr_3 = (int)ptr_3 + sizeof *liste;
    }
    est équivalente à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char * ptr_3_10;
    ...
    ptr_3_10 = (char *)liste;
    for (i = 0; i < 3 * 10; i++) {
        printf("%c", *ptr_3_10); 
    	ptr_3_10++;
        if (((i+1) % 10) == 0) { 
          printf("\n");
        }
    }

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut
    Merci beaucoup à vous deux pour la description et votre solution.

  5. #5
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Le problème majeur est de vouloir imposer au compilateur d'accepter une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        char **ptr_3;
        const char liste[3][11] = {
            {"azertyuiop"},
            {"qsdfghjklm"},
            {"wxcvbn"}
        };
    ...
       ptr_3 = (char **)liste;
    puisqu'en aucun cas liste n'est un char **. Ce n'est pas non plus un char*, c'est un char(*)[11].
    On devrait avoir (par exemple)
    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
        int i, j;
        const char liste[3][11] = {
            {"azertyuiop"},
            {"qsdfghjklm"},
            {"wxcvbn"}
        };
        const char (*ptr_3)[11];
        const char *ptr_10;
        ptr_3 = liste;
        for (i = 0; i < 3; i++)
        {
          ptr_10 =  *ptr_3;
          for (j = 0; j < 10; j++)
          {
             printf("%c", *ptr_10);
             ptr_10 ++;
          }
          printf("\n");
          ptr_3++;
        }
    ou si on veut simplifier un peu l'écriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      typedef const char Ligne[11];
        ...
        Ligne liste[3] = {
            {"azertyuiop"},
            {"qsdfghjklm"},
            {"wxcvbn"}
        };
        Ligne *ptr_3;
        ...
    @mabu : mis à part les const qui manquent dans les définitions de ptr_3 et ptr_10 :
    1- on a un cast sauvage de liste pour le faire admettre dans ptr_3,
    2- on doit avoir un warning sur ptr_10 = ptr_3, le type des pointeurs est différent (et différent de void*)
    3- Le passage par des int pour calculer la nouvelle adresse, pointeur->int->pointeur, est barbare et non portable.
    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
       const char *ptr_10;
       const char **ptr_3;
       const char liste[3][11]= ....
      ....	
       ptr_3 = (const char **)liste; // cast sauvage
       for (i = 0; i < 3; i++)
       {
         ptr_10 = ptr_3; //  warning 
         for (j = 0; j < 10; j++)
         {
           printf("%c", *ptr_10);
           ptr_10++;
         }
         printf("\n");
         ptr_3 = (int)ptr_3 + sizeof *liste; // non portable
       }
    @jabbounet : La méthode esquive un peu la question puisqu'elle consiste à considérer le tableau à deux dimensions comme un tableau à une dimension. Ceci dit, mis à part le const qui manque dans la définition de ptr_3_10, pourquoi conserver le cast sauvage inutile ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const char * ptr_3_10;
    ...
    ptr_3_10 = liste[0];

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

Discussions similaires

  1. convertir un bstr en pointeur de char
    Par dam123 dans le forum C
    Réponses: 2
    Dernier message: 20/02/2007, 20h52
  2. Réponses: 11
    Dernier message: 03/11/2006, 23h53
  3. Réponses: 6
    Dernier message: 02/11/2006, 16h44
  4. [Console] Pointeur sur char
    Par archipel_k dans le forum C
    Réponses: 4
    Dernier message: 04/08/2006, 14h32
  5. Sizeof d'un pointeur sur char ...
    Par Mike888 dans le forum C
    Réponses: 8
    Dernier message: 03/11/2005, 13h04

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