|
|
|
|
Bonjour,
J'ai envoyé ma réponse pendant deux jours mais vous m'avez pas répondu à ma question SVP essayez le maximum possible à m'envoyez la réponse à trés bientôt car vraiment j'ai une grande difficulté concernant le pointeur et surtout sur le forçage et les opérations SVP vous êtes le seul et le dernier espoir et la dernière solution que j'ai trouvé enfin en cherchant sur la toile car avant je connue pas ce forum .
DONC:
Je vais vous montrer comment forçer le type d'un pointeur à partir d'un exemple:
char *p;
p=(char*)malloc(5);
---> on forçe le type de pointeur retourné par malloc à être char.
celui là je l'ai connue mais j'ai vous demandé de m'aider à comprendre à partir d'un exercice comme un exemple qui s'intèresse sur les opérations et le forçage de type sur le pointeur et si vous ne dérrangez pas aidez moi à mieux comprendre la notion du pointeur SVP essayez encore pour m'aidez
je compte sur vous et sur vous competances excellentes car j'en ai besoin primo pour mon savoir et pour mon devoir surveillé pour que je sais répondre aux questions comme vous l'aviez dis et je parle du côté algorithmique ou bien du langage C et MERCI BEAUCOUP.
Configuration: Windows Vista Internet Explorer 7.0
Bon déjà ce n'est pas la peine de mettre un titre en majuscule, ça pique les yeux.
p=(char*)malloc(5); ne veut rien dire, car là tu alloues une place de 5 octets en mémoire alors qu'un char occupe en mémoire sizeof(char) soit 1 octet. Si tu veux allouer un tableau de 5 caractères il serait plus propre d'écrire : p=(char*)malloc(5*sizeof(char)); Maintenant il faut que tu comprennes le principe de pointeur. Qu'est ce qu'un pointeur ? juste une adresse ! Un pointeur c'est juste une adresse. Vois ça comme un entier. Peu importe de quoi il s'agit c'est toujours une adresse. Ainsi sur une architecture 32 bits (ou les adresses sont stockées sur 32 bits), peut importe que tu parles d'un void *, d'un char * ou d'un pouet *, ça fait 4 octets (4 * 8 = 32 bits). La valeur que stocke un pointeur est interprétée comme une adresse grâce à l'opérateur *. L'opérateur & permet de récupérer l'adresse d'une variable. Par exemple quand tu peux écrire : char c = 'a'; char *pc = &c; La variable pc fait 32 bits et stocke l'adresse mémoire de la variable c. Comme la variable pc est initialisée avec l'adresse de quelque chose qui est encore en mémoire et de type char, ça à du sens d'interpréter ce qui est à l'adresse *pc et de considérer ce qui s'y trouve comme un char (en l'occurrence le caractère 'a'). On pourrait donc se contenter de manipuler uniquement des adresses génériques (notées void *). Alors quel intérêt de typer un pointeur ? Simplement interpréter plus facilement ce qui se trouve à cette adresse. Si je manipule un pointeur pc de type char *, alors en écrivant *pc je suis sensé espérer un char. Notion de scope Petit rappel : une variable est désallouée en C lorsqu'on atteint l'accolade fermante de son scope (horizon). { // début du scope de a
int a;
{ // début du scope de b
int b;
//...
} // fin du scope de b
} // fin du scope de a
Un scope inclue également les paires d'accolades définies par une fonction ou un bloc d'instruction, par exemple un if(...){ ... }, un for(...){....}. Bref toute paire d'accolade est un scope, hormis les déclarations de types (struct ....{...}, enum ...{...}, class...{...}). Qu'est ce qu'une erreur de segmentation ? Si tu évalues *pc et que l'adresse pc n'a pas été initialisée (par exemple par un malloc ou l'adresse d'un objet qui existe déjà en mémoire et qui n'a pas été désalloué entretemps), alors tu auras une magnifique erreur de segmentation. Exemple :
char *pc;
{
char c = 'a';
printf("%c\n",a);
pc = *a;
printf("%c\n",*pc);
} // la variable c est désallouée
//...
//...
printf("%c\n",*pc); // n'a plus de sens (sauf si tu as de la chance)
Autre exemple : char *pc; // pc n'est pas intialisé
// pc contient une valeur aléatoire qui correspond
// très probablement à une adresse invalide
printf("%c\n",*pc); // erreur de segmentation
Que fait un malloc ? Un malloc s'occupe d'allouer une plage mémoire de taille donnée et retourne l'adresse de cette plage. C'est donc une bonne manière d'initialiser un pointeur. Exemple : // alloue une plage mémoire qui fait 10*sizeof(int) int *p = (int *)malloc(10*sizeof(int)); Libre à toi de caster cette adresse en ce que tu veux, on s'en fout c'est juste un espace mémoire. Si la variable p sera désallouée à la fin de son scope en tant que variable locale, ce n'est pas le cas de cette plage qui ne correspond pas à une variable locale. Ainsi, la zone mémoire située à cette adresse devra être libérée quand elle ne sera plus utilisée avec un free : {
int *p = (int *)malloc(10*sizeof(int));
// ...
free(p); // <-- désalloue ce qui est à l'adresse p
} // désalloue p en tant que variable locale de ce scope
Bien entendu, rien ne t'oblige à désallouer p dans le même scope, c'est même souvent rarement le cas. En général on a souvent une fonction qui alloue un objet avec des malloc, et une fonction qui le détruit. #include <stdlib.h>
struct pouet{
char *s;
};
struct pouet create(){
pouet plop;
plop.s = (char *)malloc(10*sizeof(char));
return plop;
}
void destroy(struct pouet *pplop){
free((*pplop).s); // ou free(p->s);
}
int main(){
struct pouet plop = create();
// ... j'utilise plop
destroy(&plop); // sans cette instruction, plop.s ne serait jamais désallouée !
return 0;
}
Quoi qu'il en soit, qui dit malloc dit free. Les "tableaux" Typer des pointeurs permet de manipuler des "tableaux". En soi, il n'y a pas vraiment de tableau en C. C'est plus un raccourci syntaxique ou une vue de l'esprit. Si tu écris : char buffer[100]; c'est comme si tu déclarais 100 variables de types char à la suite. Le premier caractère se trouve à l'adresse buffer. Ainsi tu dois voir la variable buffer comme un char *. Cependant à la fin du scope de buffer, les 100 caractères consécutifs placés à l'adresse buffer sont désalloués. Ces 100 caractères sont adjacents en mémoire (et placés tous les sizeof(char) en partant de l'adresse du premier caractère, buffer). Ainsi, écrire : buffer[69] ... est équivalent à écrire : *(buffer + 69) (c'est-à-dire l'adresse de buffer décalées de 69*sizeof(char) puisque buffer est un char *. Ainsi tu vois l'autre intérêt de typer un pointeur : l'opérateur + permet de se décaler du bon nombre de bit. Si je manipulais un int *, l'adresse serait incrémentée de 69*sizeof(int). Évidemment, si tu cherches à accéder à buffer[200], tu atterriras bien après le 100e caractère... et tu auras probablement une belle erreur de segmentation. Ainsi, écrire une chaîne revient à écrire : void ecrire(char *s){
unsigned i;
for(i=0;s[i]!='\0';++i){
// lire le caractère placé i*sizeof(char) après &s[0] (== s)
printf("%c",s[i]);
}
}
ou encore : void ecrire(char *s){
//++s décale s de sizeof(char) à chaque itération
for(;*s!='\0';++s){ // s se décale à chaque itération
printf("%c",*s);
}
}
En espérant que c'est plus clair pour toi... Arbre de dérivation Dans les programmes un peu évolué, il est fréquent d'avoir des structures qui pointent vers des structures qui elles mêmes pointent vers des structures. Mais le principe reste identique. On a déjà vu que (*p).champ s'écrivait aussi p->champ. Voici un exemple ou la notation avec des flèches devient plus parlante : #include <stdio.h>
struct plop1{
char mon_char;
};
struct plop2{
struct plop1 pplop1;
};
struct plop3{
struct plop2 pplop2;
};
int main(){
struct plop1 x1;
struct plop2 x2;
struct plop3 x3;
x1.mon_char = 'a';
x2.pplop1 = &x1;
x3.pplop2 = &x2;
printf("%c\n",x3->pplop2->pplop1->mon_char); // écrit 'a'
return 0;
}
Bonne chance
|
Bonjour
|
J'ai pas compris qu'est ce que c'est un scope et je sais que struct c'est pour déclarer un enregistrement parlant algorithmiquement mais j'ai pas compris que veut dire par pouet et pouet plop et j'ai pas compris cet exemple.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{ // <-- début scope de la fonction main()
char *s; // variable
{ // <-- début d'un scope (que je vais appeler B, comme bloc)
char buffer[255]; // variable locale du scope B
int n;
scanf("%s",buffer);
n = strlen(buffer);
// la chaine est de longueur n, +1 caractère pour stocker '\0'
s = (char *) malloc(sizeof(char)*(n+1)); // <-- cast
strcpy(s,buffer);
} // <-- fin du scope B : ses variables locales (buffer, n) sont désallouées
printf("s = %s\n",s);
free(s); // <-- libère la mémoire à l'adresse s (allouée par malloc)
return 0;
} // <-- fin du scope A, s est libérée (mais pas ce qui s'y trouve, d'où le free)
Bonne chance
|
Je pense que tu devrais commencer par lire un cours de langage C, ce sera plus simple pour nous deux.
|