Plantage: strchr() avec un char **

Plantage: strchr() avec un char ** - C - Programmation

Marsh Posté le 24-11-2007 à 10:57:42    

Bonour je vous demande votre aide pour trouver mon erreur. Mon programme plante (fermeture de la console) sur l'utilisation de la fonction strchr().  
 
Voilà un programme qui fait apparaitre l'erreur:

Code :
  1. #include <stdio.h>
  2. void fonction(char **chaine)
  3. {
  4.     char *p = strchr(*chaine,'\n');//Plantage ici
  5. }
  6. int main(void)
  7. {
  8.     char mot[]="bonjour";
  9.     fonction(&mot);
  10.     return 0;
  11. }


 
srtchr admet en argument un pointeur sur char et un entier. Dans la fonction:
chaine = pointeur sur un pointeur de char
*chaine = pointeur de char
 
Je ne comprends pas pour ça plante alors que j'ai bien mis un pointeur de char dans strchr()
 
Merci d'avance.


Message édité par ngkreator le 24-11-2007 à 11:00:26
Reply

Marsh Posté le 24-11-2007 à 10:57:42   

Reply

Marsh Posté le 24-11-2007 à 12:03:40    

"&mot" c'est la même chose que "mot", et c'est l'adresse du premier élément du tableau. C'est assimilable à un char *, pas à un char **.
 
Edit : si tu as besoin de passer par un char ** (je vois pas trop pourquoi dans ton exemple, mais bon), fait toi un variable "char  *motptr = mot;" et passes &mot à ta fonction.

Message cité 1 fois
Message édité par matafan le 24-11-2007 à 12:05:44
Reply

Marsh Posté le 24-11-2007 à 12:05:11    

Voici une version qui devrait mieux marcher :

Code :
  1. #include <stdio.h>
  2. void fonction(char *chaine)
  3. {
  4.     char *p = strchr(chaine,'\n');
  5. }
  6. int main(void)
  7. {
  8.     char mot[]="bonjour";
  9.     fonction(mot);
  10.     return 0;
  11. }

Reply

Marsh Posté le 24-11-2007 à 12:19:49    

matafan a écrit :

"&mot" c'est la même chose que "mot", et c'est l'adresse du premier élément du tableau. C'est assimilable à un char *, pas à un char **.

L'adresse du 1er élément du tableau ne serait-ce pas plutôt: &mot[0] ou mot tout court? Pour moi &mot c'est l'adresse de l'emplacement du pointeur mot. Ce qui serait équivalant à faire:
 

Code :
  1. char mot[]="bonjour";
  2. char *p;
  3. p=&mot;
  4.     fonction(p);
  5.     return 0;
  6. }


 
Je me trompe peut être?
 

matafan a écrit :

Edit : si tu as besoin de passer par un char ** (je vois pas trop pourquoi dans ton exemple, mais bon), fait toi un variable "char  *motptr = mot;" et passes &mot à ta fonction.

Je ne comprend pas en fait là.
 

olivthill a écrit :

Voici une version qui devrait mieux marcher :

Code :
  1. #include <stdio.h>
  2. void fonction(char *chaine)
  3. {
  4.     char *p = strchr(chaine,'\n');
  5. }
  6. int main(void)
  7. {
  8.     char mot[]="bonjour";
  9.     fonction(mot);
  10.     return 0;
  11. }


Oui bien sûr que ça marche. Tu as contourné le problème en le simplifiant.  
 
Le problème c'est que j'ai besoin de modifier le pointeur chaine. Ce petit bout de programme n'est là que pour faire apparaitre l'erreur de manière simple. Donc c'est normal que vous ne voyez pas l'intérêt de passer par un char** au lieu d'un simple char*.

Message cité 2 fois
Message édité par ngkreator le 24-11-2007 à 12:59:15
Reply

Marsh Posté le 24-11-2007 à 12:23:29    

Sinon voilà la vraie fonction:
 

Code :
  1. int nettoyer_chaine(char **chaine)
  2. {
  3.     char *p = strchr((*chaine),'\n');
  4.     if(p!=NULL)
  5.     {
  6.         *p = '\0';
  7.         *chaine = realloc(*chaine,(strlen(*chaine)+1)*sizeof(char));
  8.         if(*chaine!=NULL) return 0;
  9.         else return -1;
  10.     }
  11.     else
  12.         return -1;
  13. }


Message édité par ngkreator le 24-11-2007 à 12:24:27
Reply

Marsh Posté le 24-11-2007 à 13:22:30    

Voici un exemple utilisant nettoyer_chaine()

Code :
  1. int main(void)
  2. {
  3.     char mot[]="bonjour";
  4.     char *pmot = mot;
  5.     nettoyer_chaine(pmot);
  6.     return 0;
  7. }

Reply

Marsh Posté le 24-11-2007 à 13:32:30    

Pour enlever le "\n" de fin de chaine, la fonction nettoyer_chaine() serait avantagement remplacée par

int right_trim(char *s)
{
   int lg;
   lg = strlen(s);
   while (lg > 0 && (s[lg - 1] <= ' '))
      s[--lg] = '\0';
 
   return TRUE;
}
int main(void)
{
    char mot[]="bonjour   \n";
 
    printf("mot=%s.\n",mot); // debug
    right_trim(mot);
    printf("mot=%s.\n",mot); // debug
 
    return 0;
}

L'avantage est qu'il n'y a pas d'appel au realloc() qui est très lourd en ressources. En plus cette fonction enlève aussi les '\r' et les espaces en fin de chaine.

Message cité 1 fois
Message édité par olivthill le 24-11-2007 à 13:34:19
Reply

Marsh Posté le 24-11-2007 à 14:24:33    

olivthill a écrit :

Voici un exemple utilisant nettoyer_chaine()

Code :
  1. int main(void)
  2. {
  3.     char mot[]="bonjour";
  4.     char *pmot = mot;
  5.     nettoyer_chaine(pmot);
  6.     return 0;
  7. }



 
Donc voilà. Pour moi c'est équivalant à ce que j'avais écrit:
 

Code :
  1. int main(void)
  2. {
  3.     char mot[]="bonjour";
  4.     nettoyer_chaine(mot);
  5.     return 0;
  6. }


 
Les 2 versions plantent, et pour cause elles sont toutes deux équivalentes à celle du programme de mon 1er post.
 
 

olivthill a écrit :

Pour enlever le "\n" de fin de chaine, la fonction nettoyer_chaine() serait avantagement remplacée par

int right_trim(char *s)
{
   int lg;
   lg = strlen(s);
   while (lg > 0 && (s[lg - 1] <= ' '))
      s[--lg] = '\0';
 
   return TRUE;
}
int main(void)
{
    char mot[]="bonjour   \n";
 
    printf("mot=%s.\n",mot); // debug
    right_trim(mot);
    printf("mot=%s.\n",mot); // debug
 
    return 0;
}

L'avantage est qu'il n'y a pas d'appel au realloc() qui est très lourd en ressources. En plus cette fonction enlève aussi les '\r' et les espaces en fin de chaine.


Elle fonctionne très bien :)  Mais mon but est seulement de transformer une chaine de cette manière:
 
{'b','l','a',' ','b','l','a','\n','\0'}   ->  {'b','l','a',' ','b','l','a','\0'}
 
Je récupère des chaines d'un fichier texte écrit par mon programme (donc bien formatées). Ta fonction fonctionne parfaitement pour obtenir ce résultat mais fait un travail en trop dont je n'ai pas besoin.
 
J'avais donc fait cette fonction:

Code :
  1. int nettoyer_chaine(char *chaine)
  2. {
  3.     char *p = strchr(chaine,'\n');
  4.     if(p)
  5.     {
  6.         *p = '\0';
  7.         return 0;
  8.     }
  9.     else
  10.         return -1;
  11. }


 
Elle remplit bien son rôle et ne plante pas. Le seul problème c'est que ta fonction et cette dernière transforment en réalité les chaines de cette manière:
 
 
{'b','l','a',' ','b','l','a','\n','\0'}   ->  {'b','l','a',' ','b','l','a','\0','\0'}  
 
Alors que je veux raccourcir la chaine:
 
{'b','l','a',' ','b','l','a','\n','\0'}   ->  {'b','l','a',' ','b','l','a','\0'}
 
C'est pour ça que je suis obligé de réallouer ma chaine, donc de la faire passer par un double pointeur pour pouvoir la modifier (sa longueur).
 
Donc j'en reste au même point:
- Pourquoi ma fonction (1er post) plante?


Message édité par ngkreator le 24-11-2007 à 14:29:57
Reply

Marsh Posté le 24-11-2007 à 17:00:51    

Je pense que realloc plante car il ne marche que si la chaine a été allouée précedemment par malloc ou par une fonction du même genre. Or dans l'exemple, la chaine n'est pas allouée, elle est définie sur la pile.
Par ailleurs, si vous saviez ce qu'il y a derrière realloc (et malloc aussi), vous comprendriez que c'est une hérésie de l'utiliser pour des chaines de moins de 2000 octets. Ces fonctions utilisent beaucoup de ressources CPU et de resources en mémoire, beaucoup plus que vous ne semblez le penser. Renseignez-vous. Je parle en connaissance de cause, ayant moi-même dû réécrire ce genre de fonctions pour un compilateur.

Reply

Marsh Posté le 24-11-2007 à 17:20:22    

ngkreator a écrit :

L'adresse du 1er élément du tableau ne serait-ce pas plutôt: &mot[0] ou mot tout court? Pour moi &mot c'est l'adresse de l'emplacement du pointeur mot. Ce qui serait équivalant à faire:
 

Code :
  1. char mot[]="bonjour";
  2. char *p;
  3. p=&mot;
  4.     fonction(p);
  5.     return 0;
  6. }


 
Je me trompe peut être?


Oui tu te trompes ;)
 
En fait le truc c'est que "mot" n'a pas d'adresse. Comme je l'ai dit, "&mot" c'est exactement la même chose que "mot" tout court, ou que "&mot[0]". C'est tout pareil. Il n'y a aucun moyen de récupérer l'adresse à laquelle l'adresse du premier élément est stockée, pour la bonne raison qu'elle n'est stockée nul part, sauf dans la mémoire du compilo puis dans le texte du programe (sous la forme d'un offset par rapport au pointeur de pile dans le cas présent).

Reply

Marsh Posté le 24-11-2007 à 17:20:22   

Reply

Marsh Posté le 24-11-2007 à 17:43:54    

olivthill a écrit :

Je pense que realloc plante car il ne marche que si la chaine a été allouée précedemment par malloc ou par une fonction du même genre. Or dans l'exemple, la chaine n'est pas allouée, elle est définie sur la pile.


C'est ce que j'ai pensé au début, mais d'après: http://www.cplusplus.com/reference [...] alloc.html

Citation :

In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.


realloc peut être appliqué à un pointeur NULL. Alors du coup j'ai un doute. Mais après réflection, ma fonction simplifié sans realloc plante quand même. Dans les 2 cas ça plante sur strchr. Qu l'utilisation de realloc soit erronée ou pas c'est donc bien strchr qui fait planter la fonction. Mais j'attend de voir d'autre conseils pour realloc.
 

olivthill a écrit :


Par ailleurs, si vous saviez ce qu'il y a derrière realloc (et malloc aussi), vous comprendriez que c'est une hérésie de l'utiliser pour des chaines de moins de 2000 octets. Ces fonctions utilisent beaucoup de ressources CPU et de resources en mémoire, beaucoup plus que vous ne semblez le penser. Renseignez-vous. Je parle en connaissance de cause, ayant moi-même dû réécrire ce genre de fonctions pour un compilateur.

Je veux bien vous croire :jap:  Que faire alors?
 

matafan a écrit :


Oui tu te trompes ;)
 
En fait le truc c'est que "mot" n'a pas d'adresse. Comme je l'ai dit, "&mot" c'est exactement la même chose que "mot" tout court, ou que "&mot[0]". C'est tout pareil. Il n'y a aucun moyen de récupérer l'adresse à laquelle l'adresse du premier élément est stockée, pour la bonne raison qu'elle n'est stockée nul part, sauf dans la mémoire du compilo puis dans le texte du programe (sous la forme d'un offset par rapport au pointeur de pile dans le cas présent).

J'ai de gros doutes là dessus. Surtout pour: &pointeur = pointeur [:pingouino]
 
Par exemple ici sur le tutorial des listes chainées:  http://chgi.developpez.com/pile/

Code :
  1. void Push(pile **p, int Val)
  2. {
  3.         pile *element = malloc(sizeof(pile));
  4.         if(!element) exit(1);     /* Si l'allocation a échouée. */
  5.         element->valeur = Val;
  6.         element->prec = *p;
  7.         *p = element;       /* Le pointeur pointe sur le dernier élément. */
  8. }


Code :
  1. Push(&MaPile, 10);


 

Citation :

La fonction reçoit comme paramètres la valeur que l'on veut mémoriser mais aussi un pointeur sur le pointeur identifiant la pile.


 
Dans cet exemple un pointeur sur une structure de type pile a une adresse puisque qu'ils utilisent un pointeur sur ce pointeur. Comme on le voit il est possible d'écrire &maPile qui est l'adresse du pointeur vers la pile (pas maPile).
 
Donc même raisonnement avec un pointeur sur un char. Le pointeur de char n'est rien d'autre qu'un emplacement mémoire contenant l'adresse du char. Qui dit emplacement mémoire dit adresse. Donc ce pointeur de char a une adresse.
 
 
J'attends vos corrections sur ce que je viens de dire, et surtout une solution mon problème. Bon pour l'instant je continu le programme à coté mais c'est dommage de ne pas comprendre pourquoi ça ne marche pas.

Message cité 1 fois
Message édité par ngkreator le 24-11-2007 à 17:46:17
Reply

Marsh Posté le 24-11-2007 à 19:36:35    

ngkreator a écrit :

J'ai de gros doutes là dessus. Surtout pour: &pointeur = pointeur [:pingouino.


Ah mais j'ai pas dit "&pointeur == pointeur", j'ai dit "&tableau == tableau". Faut pas confondre tableau et pointeur, même si sur bien des points les deux sont assimilables.
 

Reply

Marsh Posté le 24-11-2007 à 20:04:38    

matafan a écrit :


Ah mais j'ai pas dit "&pointeur == pointeur", j'ai dit "&tableau == tableau". Faut pas confondre tableau et pointeur, même si sur bien des points les deux sont assimilables.
 


Tu parlais de mot: pour moi mot est un pointeur dans ton post.
C'est quoi un tableau pour toi? Parce qu'un tableau ça n'existe pas en C non?

Reply

Marsh Posté le 24-11-2007 à 20:50:56    

char *pointer = "bonjour" : pointeur
char array[] = "bonjour" : tableau
 
* et [] ce ne sont pas deux notations pour la même choses. Ce sont vraiment deux choses différentes.

Reply

Marsh Posté le 24-11-2007 à 21:47:49    

ngkreator a écrit :

L'adresse du 1er élément du tableau ne serait-ce pas plutôt: &mot[0] ou mot tout court? Pour moi &mot c'est l'adresse de l'emplacement du pointeur mot.


Sauf qu'ici, 'mot' n'est pas un pointeur mais un tableau.
 
&mot est l'adresse d'un tableau de 8 char, et son type est (char*)[8], ce qui est très différent de char**.
 
Tu confonds avec :  

Code :
  1. char const *p = "bonjour";


Là, p est de type char const *. Tu peux passer son adresse (&p) à une fonction avec un paramètre de type char const **, ce qui permet de modifier la valeur du pointeur...
 
 
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-11-2007 à 09:43:28    

Après vos 2 derniers posts je viens d'apprendre qu'on appelle tableau un pointeur constant. Je ne savait pas que: type tab[] équivalait à type *const tab
 
Donc je ne peux pas modifier l'adresse d'un tableau. Donc je dois créer un pointeur pmot qui prend l'adresse du tableau. Je passe &pmot à ma fonction pour qu'elle puisse modifier ce pointeur pmot:
 

Code :
  1. #include <stdio.h>
  2. int nettoyer_chaine(char **chaine)
  3. {
  4.     char *p = strchr((*chaine),'\n');//Ca plante ici pas sur realloc!
  5.     if(p!=NULL)
  6.     {
  7.         *p = '\0';
  8.         *chaine = realloc(*chaine,(strlen(*chaine)+1)*sizeof(char));
  9.         if(*chaine!=NULL) return 0;
  10.         else return -1;
  11.     }
  12.     else
  13.         return -1;
  14. }
  15. int main(void)
  16. {
  17.     char mot[]="bonjour";
  18.     char *pmot = mot;
  19.     nettoyer_chaine(&pmot);
  20.     return 0;
  21. }


 

  • Ca plante toujours sur la fonction strchr (pas sur la realloc). Pourquoi? J'ai donné les bons arguments il me semble.


  • matafan >> Je ne comprends toujours pas pourquoi: "&tableau == tableau" Même si un tableau n'est pas un pointeur "classique", ça reste un pointeur (constant certes) qui possède une adresse, non?


  • Y-a-t-il une autre solution (un autre algorithme) pour raccourcir ma chaine sans realloc puisqu'apparemment d'après olivthill c'est une fonction lourde? Je pourrais créer une autre chaine de la bonne longueur dans ma fonction nettoyer_chaine() puis la renvoyer par return. Mais j'aimerais plutôt garder le retour pour renvoyer l'erreur et modifier une chaine en argument.


  • Est-ce que je dois l'avoir sur la conscience le fait de me balader avec des chaines de la forme: {'b','l','a',' ','b','l','a','\0','\0','\0','\0','\0','\0'}  au lieu de   les raccourcir: {'b','l','a',' ','b','l','a','\0'} ? Sinon mon problème ne se pose plus et je n'ai pas besoin de raccourcir mes chaines.


Message édité par ngkreator le 25-11-2007 à 10:03:29
Reply

Marsh Posté le 25-11-2007 à 10:13:11    

ngkreator a écrit :

  • Y-a-t-il une autre solution (un autre algorithme) pour raccourcir ma chaine sans realloc puisqu'apparemment d'après olivthill c'est une fonction lourde? Je pourrais créer une autre chaine de la bonne longueur dans ma fonction nettoyer_chaine() puis la renvoyer par return. Mais j'aimerais plutôt garder le retour pour renvoyer l'erreur et modifier une chaine en argument.

Ca n'a aucun intérêt de raccourcir une chaine. Suite au 'nettoyage' d'une chaine modifiable, le 0 final se trouve placé à un endroit tel que la longueur de la chaine est modifiée (vérifible avec strlen()). Par contren, la taile du tableau de char est inchangée et oui, quelques byes sont inutilisables. C'est grave ?

 

Mais si tu y tiens, elle doit être allouée dynamiquement (tableau de char : malloc()), initialisée, puis nettoyée et enfin modifiée avec realloc().

 

Il ne faut lancer ce mécanisme que si ça vaut vraiment le coup (gagner des dizaines de bytes). Si c'est pour gagner 4 bytes, c'est pas la peine... D'ailleurs, il vaut mieux raisonner en, %. En dessous de 20% de gain, je dirais qu'on perd son temps...

 

Ton code est incomplet :


Project   : Forums
Compiler  : GNU GCC Compiler (called directly)
Directory : C:\dev\forums\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.c
main.c: In function `nettoyer_chaine':
main.c:5: warning: implicit declaration of function `strchr'
main.c:9: warning: implicit declaration of function `realloc'
main.c:9: warning: implicit declaration of function `strlen'
main.c:9: warning: assignment makes pointer from integer without a cast
main.c:25:2: warning: no newline at end of file
Linking console executable: console.exe
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 5 warnings


La forme 'canonique' est

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. void nettoyer_chaine (char *chaine)
  4. {
  5.    char *p = strchr (chaine, '\n');
  6.    if (p != NULL)
  7.    {
  8.       *p = '\0';
  9.    }
  10. }
  11. int main (void)
  12. {
  13.    char mot[] = "bonjour\n";
  14.    printf ("'%s'\n", mot);
  15.    nettoyer_chaine (mot);
  16.    printf ("'%s'\n", mot);
  17.    return 0;
  18. }


Et ça donne :


'bonjour
'
'bonjour'

 

Press ENTER to continue.


Il n'y a aucun intérêt à faire plus compliqué que ça... La simplicité est souvent gage de réussite...


Message édité par Emmanuel Delahaye le 25-11-2007 à 11:39:59

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-11-2007 à 10:24:01    

Ah mais j'ai oublié string.h! Je fais toujours des erreurs à la con.  Ca marche avec. Merci :jap:  
 
Mon compilateur doit être mal configuré il ne m'avait pas prévenu: j'ai aussi mingw fournit avec Codeblocks dont j'ai laissé les options par défault. Il faut que je trouve un tuto pour trouver les options à cocher.
 
Donc finalement tu me dis que c'est inutile de raccourcir la chaine. C'est vrai surtout que c'est une seule chaine utilisé en dehors de toute boucle.
 
La seule question qui me reste:
 

  • matafan >> Je ne comprends toujours pas pourquoi: "&tableau == tableau" Même si un tableau n'est pas un pointeur "classique", ça reste un pointeur (constant certes) qui possède une adresse, non?


Edit: j'avais oublié stdlib aussi, mais je vois que tu les as rajoutés :jap:

Message cité 2 fois
Message édité par ngkreator le 25-11-2007 à 10:40:21
Reply

Marsh Posté le 25-11-2007 à 11:01:21    

ngkreator a écrit :

La seule question qui me reste:
 

  • matafan >> Je ne comprends toujours pas pourquoi: "&tableau == tableau" Même si un tableau n'est pas un pointeur "classique", ça reste un pointeur (constant certes) qui possède une adresse, non?

"&tableau == tableau" parce que c'est comme ça, c'est deux notations (avec ou sans le & ) pour désigner la même chose, à savoir l'adresse du premier élément. C'est le C, c'est comme ça et on n'y peut rien.
 
Ensuite je le répète, un tableau ce n'est pas la même chose qu'un pointer, fût-il conststant. Un tableau c'est une suite d'octets consécutifs en mémoire, dont l'adresse n'est stockée nul part physiquement (en fait elle est hardcodée dans le texte du programe, d'une manière où d'une autre). Un variable de type tableau n'a pas d'adresse. En fait elle n'as même pas d'existance en tant que variable. Il n'y a pas de mot mémoire où est stocké l'adresse du premier élément. Un pointeur au contraire (et le fait qu'il soit const ne change rien à l'affaire), c'est une vraie variable, avec une adresse mémoire.
 
Tu n'as pas l'air de vouloir me croire, donc fait l'essai toi même :

Code :
  1. #include <stdio.h>
  2. int
  3. main()
  4. {
  5.         char array[]="Je ne confond pas tableau et pointeur";
  6.         const char *pointer = "Je ne confond pas tableau et pointeur";
  7.         printf("%p %p\n", array, &array);
  8.         printf("%p %p\n", pointer, &pointer);
  9.         return 0;
  10. }


Et pour enfoncer encore le clou, affiche un sizeof array et un sizeof pointer. Tu verra si tableau c'est la même chose qu'un pointeur.

Reply

Marsh Posté le 25-11-2007 à 11:19:12    

matafan a écrit :

Tu n'as pas l'air de vouloir me croire, donc fait l'essai toi même :


 [:ddr555]  Si maintenant tu m'as convaincu. Déjà &array == array mais en plus sizeof(array) donne la taille du tableau! J'ai eu du mal mais c'est bon maintenant je te crois :D
 
Bon ben tout est limpide, enfin je crois. Un grand merci à tous!


Message édité par ngkreator le 25-11-2007 à 11:20:53
Reply

Marsh Posté le 25-11-2007 à 11:42:14    

ngkreator a écrit :

Ah mais j'ai oublié string.h! Je fais toujours des erreurs à la con.  Ca marche avec. Merci :jap:  
 
Mon compilateur doit être mal configuré il ne m'avait pas prévenu: j'ai aussi mingw fournit avec Codeblocks dont j'ai laissé les options par défault. Il faut que je trouve un tuto pour trouver les options à cocher.


 
http://mapage.noos.fr/emdel/codage.htm#cfg_compilo

Citation :


Donc finalement tu me dis que c'est inutile de raccourcir la chaine. C'est vrai surtout que c'est une seule chaine utilisé en dehors de toute boucle.


Euh, je ne vois pas le rapport...
 

Citation :

Edit: j'avais oublié stdlib aussi, mais je vois que tu les as rajoutés :jap:


que j'ai finalement retiré, car mon code ne l'utilise pas...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-11-2007 à 11:48:39    

matafan a écrit :


"&tableau == tableau" parce que c'est comme ça, c'est deux notations (avec ou sans le & ) pour désigner la même chose, à savoir l'adresse du premier élément. C'est le C, c'est comme ça et on n'y peut rien.


C'est un pe plus subtil que ça. En fait, "&tableau == tableau" est vrai sur le plan de la valeur, mais faux sur le plan du type.

 

En effet, pout un tableau a de type T et de taille N, a est de type T* (adresse d'un élément), alors que &a est de type (T*)[N] (adresse d'un tableau)

 

Ca change tout si on utilise l'arithmétique des pointeurs :

Code :
  1. #include <stdio.h>
  2. int main (void)
  3. {
  4.    int a[3];
  5.    printf ("%-10s = %p\n", "a", (void *) a);
  6.    printf ("%-10s = %p\n", "&a", (void *) &a);
  7.    printf ("%-10s = %p\n", "a + 1", (void *) (a + 1));
  8.    printf ("%-10s = %p\n", "&a + 1", (void *) (&a + 1));
  9.    return 0;
  10. }



a          = 0022FF60
&a         = 0022FF60
a + 1      = 0022FF64
&a + 1     = 0022FF6C

 

Press ENTER to continue.


Message édité par Emmanuel Delahaye le 25-11-2007 à 11:51:40

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-11-2007 à 12:13:14    

Emmanuel Delahaye a écrit :

Citation :

Donc finalement tu me dis que c'est inutile de raccourcir la chaine. C'est vrai surtout que c'est une seule chaine utilisé en dehors de toute boucle.


Euh, je ne vois pas le rapport...

J'ai dit n'importe quoi. J'imaginais que dans une boucle les octets inutilement réservés à la chaine allaient s'accumuler. C'est faux.
 
Sinon pour les options du compilateurs:
 

Citation :

NOTA : sur les anciennes version de gcc (< 3.4.x), remplacer -Wextra par -W


J'ai la dernière version de gcc j'imagine puisque j'ai celle qui est fournie avec Codeblocks. Or j'ai -W mais pas -Wextra.
 
En plus j'ai la plupart de ces flags qui sont inexistants:
 

Citation :

-Wall -Wextra -O -Wwrite-strings -Wstrict-prototypes -Wuninitialized
-Wunreachable-code


 
Dans ce cas il faut les insérer manuellement dans "other option" dans Codeblocks?
 
http://pix.nofrag.com/d/3/8/d34b3e0f6743c0d9459ea2403be32.jpg
 
Ah j'avais pas lu la suite qui parle de Codebloacks, désolé.


Message édité par ngkreator le 25-11-2007 à 12:25:23
Reply

Marsh Posté le 25-11-2007 à 12:35:41    

C'est super les warnings! On est carrément assisté avec tous ces warnings. Mais d'un coté ça m'a aidé à résoudre un problème qui me bloquait depuis hier. A savoir une variable compteur non initialisée à 0  :pfff:  Je fais vraiment des erreurs à la con!
 
Je pensais pas que les warnings prévenaient de ce genre d'erreur, c'est pas mal.


Message édité par ngkreator le 25-11-2007 à 12:36:03
Reply

Marsh Posté le 25-11-2007 à 12:53:14    

Merci pour le commentaire sur le type de "array" et "&array", ça m'échappait. En fait ça explique pourquoi array et &array ont la même valeur. C'est pas arbitraire, il y a une raison la dessous, tout est logique :jap:

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed