Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/09/2020, à 20:40

zephyre123

Conversion explicite sur pointeur[RESOLU]

Bonjour,

J'ai fais le programme suivant vraiment très simple mais je ne comprends absolument pas le résultat.
Le programme ci dessous ;

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char lettre = 'A';
	char *pc = &lettre;
	int *valeur_numerique = (int*) pc;
	printf("Valeur numerique de la lettre A : %d",  *valeur_numerique); // Normalement devrai afficher la valeur 65 qui correspond à la lettre A majuscule
	return EXIT_SUCCESS;
}

Je ne trouve pas la valeur 65 à laquelle je m'attendais qui corresponds à la lettre A dans la table ASCII mais un nombre vraiment bizarre.

Dernière modification par zephyre123 (Le 25/09/2020, à 22:15)

Hors ligne

#2 Le 23/09/2020, à 20:51

Nuliel

Re : Conversion explicite sur pointeur[RESOLU]

Bonjour,
Tu peux sans problème faire

#include <stdio.h>

int main(void)
{
	char lettre = 'A';
	printf("Valeur numerique de la lettre A : %d",  lettre);
	return 0;
}

C'est vachement plus simple non? Un char n'est qu'un entier avec une étiquette dessus pour dire que c'est un caractère.
#include <stdlib.h> n'est pas obligatoire, et EXIT_SUCESS n'est pas défini, il faut donc rajouter
#define EXIT_SUCCESS 0

Sinon je comprends pas ce que fait ton code

Dernière modification par Nuliel (Le 23/09/2020, à 20:53)

Hors ligne

#3 Le 23/09/2020, à 21:26

pingouinux

Re : Conversion explicite sur pointeur[RESOLU]

Bonsoir,

        printf("Valeur numerique de la lettre A (décimal) : %d\n",  *valeur_numerique);
        printf("Valeur numerique de la lettre A (hexa)    : %x\n",  *valeur_numerique);
        printf("Valeur numerique de la lettre A (carac)   : %c\n",  *valeur_numerique);

donne ce résultat

Valeur numerique de la lettre A (décimal) : 619284289
Valeur numerique de la lettre A (hexa)    : 24e98741
Valeur numerique de la lettre A (carac)   : A

En hexadécimal, on voit que l'octet de poids faible vaut 41, soit 65 en décimal.
La conversion de char* à int* fait que valeur_numerique pointe sur un entier, constitué de l'encodage de 'A' sur 1 octet, suivi de 3 autres octets.

Hors ligne

#4 Le 23/09/2020, à 21:30

zephyre123

Re : Conversion explicite sur pointeur[RESOLU]

Merci d'avoir répondu si vite mais je ne comprends pas ce que ce code fait.
Je veux savoir ce que me donne cette ligne de code :

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char lettre = 'A';
	char *pc = &lettre;
	int *valeur_numerique = (int*) pc;
	printf("Valeur numerique de la lettre A : %d",  *valeur_numerique); // QUE M'AFFICHE CETTE LIGNE DE CODE ?
	return EXIT_SUCCESS;
}

Hors ligne

#5 Le 23/09/2020, à 21:44

pingouinux

Re : Conversion explicite sur pointeur[RESOLU]

	printf("Valeur numerique de la lettre A : %d",  *valeur_numerique); // QUE M'AFFICHE CETTE LIGNE DE CODE ?

C'est ce que j'ai essayé de te dire en #3 : c'est un entier, dont l'octet de poids faible contient la lettre 'A', soit 65 en décimal, ou 41 en hexadécimal, les 3 octets suivants pouvant prendre des valeurs quelconques.

        printf("*pc (décimal) : %d\n",  *pc);
        printf("(*valeur_numerique)&0xff (décimal) : %d\n",  (*valeur_numerique)&0xff);

donne ce résultat

*pc (décimal) : 65
(*valeur_numerique)&0xff (décimal) : 65

Ajouté :
Pour récupérer l'octet de poids faible d'un entier :

octet_poids_faible = entier & 0xff

Dernière modification par pingouinux (Le 23/09/2020, à 22:11)

Hors ligne

#6 Le 24/09/2020, à 14:23

grigouille

Re : Conversion explicite sur pointeur[RESOLU]

On suppose qu'un char fait 1 octet et qu'un int fait 4 octets.

Quelque part en mémoire il y a :
0x41 0x?? 0x?? 0x??
Le pointeur 'pc' pointe sur 0x41
Le pointeur 'valeur_numerique' pointe sur 0x41 0x?? 0x?? 0x ??
L'affichage que tu demandes correspond à la transcription de ces 4 octets en un int. Ce qui est complètement aléatoire.

C'est ce que dit pingouinux quand il parle d'octet de poids faible et des 3 octets quelconques.

$ cat toto.c
#include <stdio.h>

int main(void)
{
        char lettre = 'A';
        char *pc = &lettre;
        int *valeur_numerique = (int*) pc;
        //rubbish
        printf("Valeur numerique de la lettre A : %d\n",  *valeur_numerique);
        //non rubbish
        printf("Valeur numerique de la lettre A : %d\n",  (*valeur_numerique) & 0xff);
        printf("Valeur numerique de la lettre A : %d\n",  lettre);
        return 0;
}
$
$ gcc -o toto toto.c -Wall && ./toto
Valeur numerique de la lettre A : 1618614081
Valeur numerique de la lettre A : 65
Valeur numerique de la lettre A : 65
$

Dernière modification par grigouille (Le 24/09/2020, à 14:24)


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#7 Le 24/09/2020, à 16:28

NicoApi73

Re : Conversion explicite sur pointeur[RESOLU]

Bonjour,

@zephyre123 : ce que tu fais est extrêmement dangereux (en terme de comportant attendu du programme) car tu utilises un entier qui n'a pas été alloué. En lecture ça ne pose pas de problème, si tu écris dedans si.

lettre est une variable d'un octet, contenant 'A'
pc est une variable de type pointeur, contenant l'addresse de lettre. pc est déclarée comme pointant sur un char d'un octet, ce qui est effectivement le cas.
valeur_numerique est une variable de type pointeur, contenant l'addresse de lettre. valeur_numerique est déclarée comme pointant sur un int, ce qui n'est pas le cas

Si tu affectes une valeur de type int à (*valeur_numerique), tu écrases le contenu de lettre (moyennement grave, lettre étant allouée) et tu écrases aussi le contenu des octets suivants lettre qui eux sont soit non alloué, soit alloué à une autre variable et là ça peut devenir catastrophique

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char lettre2 = 'B';
	char lettre = 'A';

	char *pc = &lettre;
	int *valeur_numerique = (int*) pc;

	printf ("Addresse de lettre2 : %p\n",&lettre2);
	printf ("Contenu de lettre2 : %d\n\n",(int)lettre2);

	printf("Valeur numerique de la lettre A : %d\n\n",  *valeur_numerique); 
	printf ("Addresse de lettre : %p\n",&lettre);
	printf ("Contenu de lettre : %d\n\n",(int)lettre);

	printf ("Addresse de pc : %p\n",&pc);
	printf ("Contenu de pc : %p\n\n",pc);
	printf ("Addresse de valeur_numerique : %p\n",&valeur_numerique);
	printf ("Contenu de valeur_numerique : %p\n\n",valeur_numerique);
	
	*valeur_numerique = 0;
	printf("Resultat apres *valeur_numerique = 0 : %d\n\n",  *valeur_numerique);
	
	printf ("Qu'est devenu lettre2 : %d",(int)lettre2);
	
	return EXIT_SUCCESS;
}
Addresse de lettre2 : 0061FF1F
Contenu de lettre2 : 66

Valeur numerique de la lettre A : -15973823

Addresse de lettre : 0061FF1E
Contenu de lettre : 65

Addresse de pc : 0061FF18
Contenu de pc : 0061FF1E

Addresse de valeur_numerique : 0061FF14
Contenu de valeur_numerique : 0061FF1E

Resultat apres *valeur_numerique = 0 : 0

Qu'est devenu lettre2 : 0

------------------
(program exited with code: 0)

L'allocation de la mémoire peut varier en fonction des compilateurs. Il est parfois nécessaire de déclarer différemment lettre et lettre2 pour avoir le résultat ci-dessus, d'autant que les valeurs de pc et valeur_numerique peuvent être affectés également en fonction de où elles sont allouées.

Dernière modification par NicoApi73 (Le 24/09/2020, à 16:30)

Hors ligne

#8 Le 24/09/2020, à 22:01

zephyre123

Re : Conversion explicite sur pointeur[RESOLU]

Merci pour toutes ces explications j'ai maintenant compris smile
Merci encore !

En revanche je n'ai absolument rien compris à ce que NicoApi73 a écrit et pourquoi la lettre2 a changé.
C'est de la magie ou quoi ? lol

Bon j'ai un peu changer ton programme NicoApi73 afin de m'y retrouver, j'ai changé les noms et les aient mis dans l'ordre croissant (lettre1 = A en premier et lettre2 = B en second)
et j'ai viré le mot contenu pour les pointeurs car sa porte à confusion.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char lettre1 = 'A';
	char lettre2 = 'B';

	char *pc = &lettre1;
	int *valeur_numerique = (int*) pc;

	printf("Valeur numerique de la lettre A : %d\n\n",  (*valeur_numerique) & 0xff); 
	printf ("Addresse de lettre1 (A) : %p\n",&lettre1);
	printf ("Contenu de lettre1  (A): %x\n\n",lettre1);

	printf ("Addresse de lettre2 (B) : %p\n",&lettre2);
	printf ("Contenu  de lettre2 (B) : %x\n\n",lettre2);

	printf ("Addresse de pc : %p\n",&pc);
	printf ("pc : %p\n\n",pc);

	printf ("Addresse de valeur_numerique : %p\n",&valeur_numerique);
	printf ("valeur_numerique : %p\n\n",valeur_numerique);
	
	*valeur_numerique = 0;

	printf("contenu de la lettre1 : %x\n\n", lettre1);
	
	printf("contenu de la lettre2 : %x\n",lettre2);

	return EXIT_SUCCESS;
}

Et sa donne ci dessous :

Valeur numerique de la lettre A : 65

Addresse de lettre1 (A) : 0x7fff2a68de16
Contenu de lettre1  (A): 41

Addresse de lettre2 (B) : 0x7fff2a68de17
Contenu  de lettre2 (B) : 42

Addresse de pc : 0x7fff2a68de18
pc : 0x7fff2a68de16

Addresse de valeur_numerique : 0x7fff2a68de20
valeur_numerique : 0x7fff2a68de16

contenu de la lettre1 : 0

contenu de la lettre2 : 0 // Pourquoi la lettre2 passe également à 0 ?

Dernière modification par zephyre123 (Le 24/09/2020, à 22:59)

Hors ligne

#9 Le 25/09/2020, à 07:21

NicoApi73

Re : Conversion explicite sur pointeur[RESOLU]

zephyre123 a écrit :

En revanche je n'ai absolument rien compris à ce que NicoApi73 a écrit et pourquoi la lettre2 a changé.
C'est de la magie ou quoi ? lol

Bonjour,

Ce n'est pas de la magie, c'est un bug de ton programme appelé débordement mémoire ou jardinage.

Quand tu déclares lettre, par char lettre, tu réserves un espace mémoire d'un char (1 octet), à l'adresse mémoire lettre.
Quand tu déclares valeur_numerique, par int * valeur_numerique, tu ne réserves pas d'espace mémoire, Tu indiques uniquement que tu utiliseras par la suite un espace mémoire de type int (4 octets), qui n'est pas encore réservé. A ce moment là, l'adresse mémoire contenue dans valeur_numerique est aléatoire.
Par tes assignations, tu mets l'adresse mémoire de l'espace réservé pour lettre dans valeur_numérique. Or la mémoire réservée est de 1 octet alors que valeur_numerique est prévue pour 4. Quand tu fais

*valeur_numerique = 0

, tu mets à 0 4 octets, donc celui qui est réservé pour lettre et les trois suivants qui sont potentiellement attribués (ici l'un d'entre eux est attribué à lettre2) et donc tu écrases lettre2.

Et c'est comme ça que tu te retrouves avec un programme qui plante ou qui ne fait pas ce que tu attends. Et ça peut devenir très compliqué pour identifier d'où vient l'erreur...

Dernière modification par NicoApi73 (Le 25/09/2020, à 08:29)

Hors ligne

#10 Le 25/09/2020, à 22:15

zephyre123

Re : Conversion explicite sur pointeur[RESOLU]

Merci NicoApi73 j'ai un peu près compris merci encore pour ces détails très précieux
Merci encore pour votre aide à tous.

Hors ligne