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 :

Tableau de pointeurs, printf => affichage adresse et valeur


Sujet :

C

  1. #1
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut Tableau de pointeurs, printf => affichage adresse et valeur
    Bonjour,

    Je cherche à faire un tableau "tab" de 4 pointeurs dans lequel je vais mettre les adresses de 4 mots déjà en mémoire quelque part. Je veux ensuite afficher le tableau d'entier contenant les adresses mémoire des 4 mots ainsi que la valeur que contiennent ces adresses. Mais j'obtiens cette erreur à la compilation : Segmentation fault (core dumped).

    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
    int main( int argc, char *argv[])
    {
    	char *mot[4]; // déclaration de 4 chaînes de caractères
    	int tab[4]; // déclaration d'un tableau de 4 cases d'entiers
     
    	mot[0]="carré";	/************************************/
    	mot[1]="rectangle";	/****  initialisation des 4 mots  ***/
    	mot[2]="triangle";	/****  quelque part en mémoire  *****/
    	mot[3]="rond";		/************************************/
     
    	printf("ADRESSE : %d | VALEUR : %s\n",mot[0],*mot);		/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %d | VALEUR : %s\n",mot[1],*(mot+1));	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %d | VALEUR : %s\n",mot[2],*(mot+2));	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %d | VALEUR : %s\n",mot[3],*(mot+3));	/* affichage adresse et valeur mot 4*/
     
    	tab[0]=(long)&mot[0];	/* on met l'adresse du mot 1 dans le tableau d'entier */
    	tab[1]=(long)&mot[1];	/* on met l'adresse du mot 2 dans le tableau d'entier */
    	tab[2]=(long)&mot[2];	/* on met l'adresse du mot 3 dans le tableau d'entier */
    	tab[3]=(long)&mot[3];	/* on met l'adresse du mot 4 dans le tableau d'entier */
     
     
    	/* à partir de la ligne ci-dessous j'ai une erreur : "Segmentation fault (core dumped)" */
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[0],*tab);	/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[1],*(tab+1));	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[2],*(tab+2));	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[3],*(tab+3));	/* affichage adresse et valeur mot 4*/
     
        return 0;
    }
    Avez-vous une piste pour résoudre ce problème ?

  2. #2
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Premiere chose : evite les accents ou caracteres speciaux si tu utilises des chaines de caracteres "basiques", ca peut poser probleme.

    Deuxieme chose : quand on affiche une adresse, on utilise plutot le flag "%p" (mais c'est pas genant...).

    Ton erreur vient de ces 4 lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    tab[0]=(long)&mot[0];	/* on met l'adresse du mot 1 dans le tableau d'entier */
    tab[1]=(long)&mot[1];	/* on met l'adresse du mot 2 dans le tableau d'entier */
    tab[2]=(long)&mot[2];	/* on met l'adresse du mot 3 dans le tableau d'entier */
    tab[3]=(long)&mot[3];	/* on met l'adresse du mot 4 dans le tableau d'entier */
    Enleve le '&' devant et tout ira bien. Tu veux juste le pointeur sur char*, pas le pointeur du pointeur.

  3. #3
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut
    Première chose notée : éviter les accents. Juste pour infos, qu'appelez-vous chaîne de caractères "basiques" ?

    Deuxième chose : merci pour l'info.

    Pour mon erreur, j'ai enlevé le "&" et effectivement cela fonctionne. Merci.

    Cependant j'ai maintenant un autre problème. Dans la dernière partie de mon code j'ai bien les 4 adresses qui s'affchent et les 4 valeurs correspondantes mais j'ai un warning (enfin 4 identiques) : warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat].

    Ce n'est qu'un warning mais je n'aime pas trainer ça. Je préfère avoir une compilation "propre".

    Comment puis-je donc afficher la valeur (chaîne de caractères) à partir de son adresse (int) ?

    Pour info mon nouveau code avec cette erreur :

    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
    int main( int argc, char *argv[])
    {
    	char *mot[4]; // déclaration de 4 chaînes de caractères
    	int tab[4]; // déclaration d'un tableau de 4 cases d'entiers
     
    	mot[0]="carre";		/************************************/
    	mot[1]="rectangle";	/****  initialisation des 4 mots  ***/
    	mot[2]="triangle";	/****  quelque part en mémoire  *****/
    	mot[3]="rond";		/************************************/
     
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[0],mot[0]);	/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[1],mot[1]);	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[2],mot[2]);	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[3],mot[3]);	/* affichage adresse et valeur mot 4*/
     
    	tab[0]=(long)mot[0];	/* on met l'adresse du mot 1 dans le tableau d'entier */
    	tab[1]=(long)mot[1];	/* on met l'adresse du mot 2 dans le tableau d'entier */
    	tab[2]=(long)mot[2];	/* on met l'adresse du mot 3 dans le tableau d'entier */
    	tab[3]=(long)mot[3];	/* on met l'adresse du mot 4 dans le tableau d'entier */
     
     
    	/* à partir de la ligne ci-dessous j'ai une erreur : test.c:288:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat] */
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[0],tab[0]);	/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[1],tab[1]);	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[2],tab[2]);	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %d | VALEUR : %s\n",tab[3],tab[3]);	/* affichage adresse et valeur mot 4*/
     
        return 0;
    }

  4. #4
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    En C, les char* sont des chaines de caracteres qui font (normalement) chacun un octet. Avec l'ascii etendu, un caractere en prend en realite plusieurs, ca peut induire en erreur, c'est pour ca qu'il vaut mieux eviter au debut.

    Une adresse reste une adresse, que ce soit un int ou un void*, au final c'est toujours un entier (seule la taille change selon si c'est un systeme 32 ou 64 bits) donc voila pour ne plus avoir le warning :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    printf("ADRESSE : %d | VALEUR : %s\n",tab[0],(char*)tab[0]);	/* affichage adresse et valeur mot 1*/
    printf("ADRESSE : %d | VALEUR : %s\n",tab[1],(char*)tab[1]);	/* affichage adresse et valeur mot 2*/
    printf("ADRESSE : %d | VALEUR : %s\n",tab[2],(char*)tab[2]);	/* affichage adresse et valeur mot 3*/
    printf("ADRESSE : %d | VALEUR : %s\n",tab[3],(char*)tab[3]);	/* affichage adresse et valeur mot 4*/

  5. #5
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut
    Ok pour l'info.

    J'avais bien essayé de mettre (char *) mais ca me génère un autre problème : warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]. Quand j'ai ce problème avec des entier je le résous avec un (long) mais pour une chaîne de caractère je n'en ai aucune idée.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Citation Envoyé par imperio Voir le message
    En C, les char* sont des chaines de caracteres qui font (normalement) chacun un octet. Avec l'ascii etendu, un caractere en prend en realite plusieurs, ca peut induire en erreur, c'est pour ca qu'il vaut mieux eviter au debut.
    Pour être précis, l'ASCII ne prend que 7 bits et c'est de l'américain: donc pas d'accent, pas de tilde et autre caractères spécifiques.
    Il y a les "code pages" qui permet de remplir les 256 vides et donc prend 1 octet: latin-1, latin-9 par exemple
    Il y a des "multi-set code pages" qui sont des "codes pages" étendues sur 2 octets: le Shift-JIS

    Et ensuite, il y a l'Unicode UTF-8, UTF-16 et UTF-32, qui gère en théorie tous les caractères.
    Ces derniers sont variables et peuvent prendre plus de 2 octets.
    En pur C, c'est géré avec les wchar_t

  7. #7
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut
    Citation Envoyé par foetus Voir le message
    Pour être précis, l'ASCII ne prend que 7 bits et c'est de l'américain: donc pas d'accent, pas de tilde et autre caractères spécifiques.
    Il y a les "code pages" qui permet de remplir les 256 vides et donc prend 1 octet: latin-1, latin-9 par exemple
    Il y a des "multi-set code pages" qui sont des "codes pages" étendues sur 2 octets: le Shift-JIS

    Et ensuite, il y a l'Unicode UTF-8, UTF-16 et UTF-32, qui gère en théorie tous les caractères.
    Ces derniers sont variables et peuvent prendre plus de 2 octets.
    En pur C, c'est géré avec les wchar_t
    Je suis sensé trouvé une piste à mon problème (warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]) avec tout ça ? Si c'est le cas je ne vois pas pas... J'ai bien essayé plusieurs types, plusieurs syntaxes, sprintf, strcpy pour transformer ce int en string mais pas de résultant positif.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Citation Envoyé par Mat08 Voir le message
    Je suis sensé trouvé une piste à mon problème (warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]) avec tout ça ? Si c'est le cas je ne vois pas pas... J'ai bien essayé plusieurs types, plusieurs syntaxes, sprintf, strcpy pour transformer ce int en string mais pas de résultant positif.

    Le message d'erreur est très clair "cast to pointer from integer of different size": tu essayes de mettre un entier dans un pointeur, entier qui n'a pas la même taille que celle d'un pointeur
    Ton tableau tab c'est un tableau qui contient quel type de données?

    Chez moi, pas d'avertissements à la compilation: Compiles-tu en 64bits?

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int tab[4]; // déclaration d'un tableau de 4 cases d'entiers 
    tab[0]=(long)&mot[0];	/* on met l'adresse du mot 1 dans le tableau d'entier */
    tab[1]=(long)&mot[1];	/* on met l'adresse du mot 2 dans le tableau d'entier */
    tab[2]=(long)&mot[2];	/* on met l'adresse du mot 3 dans le tableau d'entier */
    tab[3]=(long)&mot[3];	/* on met l'adresse du mot 4 dans le tableau d'entier */
    Tu déclares un tableau d'int mais tu y mets des longs. Déjà, il y a un problème.

    Ensuite, il existe un type spécial pour stocker des adresses dans des entiers : intptr_t (qui a une variante non signée : uintptr_t). tab devrait être un tableau de ce type pour y stocker de manière portable et sécurisée les adresses.

  10. #10
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut
    @foetus : Le tableau "tab" est déclaré en int. Je m'en sers pour mettre des adresses mémoires (donc bien des int si je ne dis pas de bétises). Oui je compile en 64 bits.

    @Bktero : J'y mets des long justement pour ne plus avoir d'avertissement (warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]). Je me doute que c'est brutal et peut-être pas la meilleur chose à faire mais c'est la seule solution que j'ai trouvé.

    Le problème est que j'ai le même warning avec un int(adresse mémoire) que je veux afficher en char * (valeur contenu à cette adresse mémoire). C'est surtout ce problème qui me gène.

    Je vais quand même étudier votre remarque à propos de intptr_t. Mais ça ne règlera surement le warning.

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Citation Envoyé par Mat08 Voir le message
    Le tableau "tab" est déclaré en int. Je m'en sers pour mettre des adresses mémoires (donc bien des int si je ne dis pas de bétises). Oui je compile en 64 bits.
    Regarde sur Google les tailles en bits des types, ... ou alors fait des sizeof

    Mais, en théorie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type \ executable  32 bit       64 bit
    int                32 bit       32 bit
    long int           32 bit       64 bit
    Donc tab contient des entiers de 32bits mais tu y mets des pointeurs de 64bits castés en 64bits

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Caster pour faire taire un warning est souvent une mauvaise idée. Il faut alors être totalement certain de ce qu'on fait et qu'on corrige effectivement le problème et non qu'on le masque en s'exposant un problème à l'exécution.

    La solution est justement intptr_t. Le tableau doit être de ce type et le cast doit se faire vers ce type.

  13. #13
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 272
    Points : 100
    Points
    100
    Par défaut
    Effectivement, intptr_t était la clé. Il faut que je me plonge plus sérieusement dans ces différents types à tête reposée.

    Mon code fonctionne maintenant en ayant mis les bons types au bon endroit (en tout cas je l'espère). Ni erreur, ni warning à la compilation. Je pense qu'il n'y a plus de chose insensée uniquement pour faire taire un warning.

    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
    int main( int argc, char *argv[])
    {
    	char *mot[4]; // déclaration de 4 chaînes de caractères
    	intptr_t tab[4]; // déclaration d'un tableau de 4 cases d'entiers
     
    	mot[0]="carre";		/************************************/
    	mot[1]="rectangle";	/****  initialisation des 4 mots  ***/
    	mot[2]="triangle";	/****  quelque part en mémoire  *****/
    	mot[3]="rond";		/************************************/
     
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[0],mot[0]);	/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[1],mot[1]);	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[2],mot[2]);	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %p | VALEUR : %s\n",mot[3],mot[3]);	/* affichage adresse et valeur mot 4*/
     
    	tab[0]=(intptr_t)mot[0];	/* on met l'adresse du mot 1 dans le tableau d'entier */
    	tab[1]=(intptr_t)mot[1];	/* on met l'adresse du mot 2 dans le tableau d'entier */
    	tab[2]=(intptr_t)mot[2];	/* on met l'adresse du mot 3 dans le tableau d'entier */
    	tab[3]=(intptr_t)mot[3];	/* on met l'adresse du mot 4 dans le tableau d'entier */
     
    	printf("ADRESSE : %d | VALEUR : %s\n",(int)tab[0],(char *)tab[0]);	/* affichage adresse et valeur mot 1*/
    	printf("ADRESSE : %d | VALEUR : %s\n",(int)tab[1],(char *)tab[1]);	/* affichage adresse et valeur mot 2*/
    	printf("ADRESSE : %d | VALEUR : %s\n",(int)tab[2],(char *)tab[2]);	/* affichage adresse et valeur mot 3*/
    	printf("ADRESSE : %d | VALEUR : %s\n",(int)tab[3],(char *)tab[3]);	/* affichage adresse et valeur mot 4*/
     
        return 0;
    }
    Merci beaucoup à tous pour votre aide.

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

Discussions similaires

  1. tableau de pointeurs
    Par seal3 dans le forum C++
    Réponses: 7
    Dernier message: 01/11/2005, 20h51
  2. Tableau de pointeurs de fonctions
    Par Alp dans le forum C++
    Réponses: 7
    Dernier message: 29/10/2005, 13h19
  3. variables tableau dans requettes mysql ... et affichage
    Par mulbek dans le forum Requêtes
    Réponses: 3
    Dernier message: 26/10/2005, 16h29
  4. Réponses: 4
    Dernier message: 12/10/2005, 21h22
  5. Réponses: 6
    Dernier message: 19/09/2005, 19h48

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