bonjour;
j'ai quelques questions a poser:
1-quelle est l'espace memoire occupé par le type enum
2-Pourquoi ce code ne marche pas:
3-dans quels cas on fait alignement de donnéesCode:
1
2
3
4
5 char *f() { char tab[4]="txt"; return tab; }
merci
Version imprimable
bonjour;
j'ai quelques questions a poser:
1-quelle est l'espace memoire occupé par le type enum
2-Pourquoi ce code ne marche pas:
3-dans quels cas on fait alignement de donnéesCode:
1
2
3
4
5 char *f() { char tab[4]="txt"; return tab; }
merci
Le meme qu'un int.
Parce que tu retournes un pointeur sur une zone memoire allouee automatiquement (alias la pile). Cette zone est liberee a la fin de la fonction.Citation:
2-Pourquoi ce code ne marche pas:
Code:
1
2
3
4
5 char *f() { char tab[4]="txt"; return tab; }
Tu n'as normalement pas a t'en occuper, le compilateur s'occupe de faire ca quand c'est necessaire pour la cible.Citation:
3-dans quels cas on fait alignement de données
merci
a ma connaissance le retour des fonctions est gardé dans la pile?Code:Cette zone est liberee a la fin de la fonction.
Tu as ecrit
Enorme erreur !!!!!!!!!!!!!!!!!!Citation:
Code:
1
2
3
4
5
6
7
8
9 char *f() // tu defins ta fonction ... peut etre ajouter void entre la parenthese suivant // le compilateur ou l'extension du fichier { char tab[4]="txt"; // une chaine de 4 dans une chaine de 4 return tab; // A priori tu renvoies un pointeur de chaine mais attention // tu as defini une chaine de 4 .. Attention au compilateur }
C'est l'erreur typique du C !!!
Sauf que !!!
tab n'existe que pendant l'appel de ta fonction !!!!!!!!!
Tu dois faire un truc du styleCode:
1
2
3
4
5 char * ch; ch=f(); // Ch pointe sur tab // f est fermee ... tab variable locale a f N'EXISTE PLUS //
et dans le progCode:
1
2
3
4
5
6
7
8 char ch[500]=""; // tu cree ta chaine avec de la place !!! void f(char * ch1) { char * txt="txt"; strcpy(ch1,txt); } ....
[-mod- Merci d'apprendre à utiliser le forum correctement (citations, balises code...) Tout est expliqué dans les règles du forum.]Code:
1
2
3 ... f(ch); ch vaut alors "txt"
La valeur oui.
Tu retournes la valeur d'un pointeur, qui pointe sur une adresse mémoire.
Cette valeur d'adresse existe toujours, tu y as accès. Mais la zone que tu avais allouée, elle, a été libérée, tu n'as donc plus accès aux valeurs.
J'espère avoir été suffisament clair ^^
PS : La balise CODE ! Nondidjiu !
NON, c'est une erreur typique à ne pas faire.Citation:
a ma connaissance le retour des fonctions est gardé dans la pile?
http://c.developpez.com/faq/c/?page=..._string_return
1) enum ... j'ai vu ... je connais pas
ce serait pas des trucs un peu comme des tableaux ???
plutot pratique dans des boucles ?
J'utilse pas ... mais j'ai deja vu
3) Tu parles d'indentement ?
Tous est affaire de convention
Tu peu ecrire comme tu veux seul la lisibilité compte
Les compilateur ignorent les espaces et saut de ligne
En fait ton programme pour le compilateur est ... sur une seule ligne
J'utilise une convention ancienne :
La convention moderne est plutot du style je croisCode:
1
2
3
4
5
6
7 void f(void) { if (0==0) { ... } }
En regle general ... Utilise un indentement de 2 ou 3 caracteres maxiCode:
1
2
3
4
5 void f(void) { if (0==0) { ... } }
si tu utilise des tabulations ... 4 if imbriques et tu vois plus ton code ...
Mais bon ... pour les if a rallonge
je fais plutot un truc du style
cela evite les indentation a rallonge ... Et ca rallonge pas le temps d'executionCode:
1
2
3
4
5
6
7
8
9
10
11
12 ok=1; if (ok) if ( ) // negation de ta condition 1 ok=0; if (ok) if ( ) // negation de ta condition 2 ok=0; .... if (ok) { ACTION !!! }
Et cela permet de rajouter un if sans indenter !!!
De maniere generale... Trouve des regles qui te plaisent ... Plutot elegantes
Et tiens toi y... Tu pourras relire tes programmes
Et si tu travailles avec des copains ... Essaie de te diriger vers leur convention...
Cela evitera des tensions
Il est clair que je ne suis pas qualifie pour ca.
J'ai dit ... j'ai vu
J'utilise pas
...
Parce que c'est d'un interet reduit
Alors j'ai regardé a nouveau
Enum c'est un ensemble fini de variables entieres
definie par des constants de type int
Cela permet de definir une variable parmi par exemple {1, 25, 78}
ou 1 25 78 sont des constantes interpertees par le compilateur
Donc en reponse ... c'est du type int.
A quoi ca sert ? ... a mon avis pas agrand chose ... sauf si on sait mettre ces donnees successivement dans une boucle..
Peut etre eclairer le programme en faisant :
enum couleur {rouge = 1, bleu = 25, vert=78};
A moins que le compilateur n'autorise pas la comparaison entre un entier et un enum.
Alors cela permettrait de verifier que le code ne sort jamais de rouge vert et bleu mais cela interdirait l'affectation d'une variable entier avec un enum.
Enfin, si ... En pascal dans mes souvenir y'avait une notion d'ensemble
Cela pourrait servir dans un truc du style en C
... Maintenant pourquoi je suis passe devant sans jamais regarder certain type d'instruction...Code:
1
2
3
4
5
6
7 int a; if (a in couleur) { // la ca evite un teste en boucle et ca c'est valable !!! // auquel cas je presenterai d'humbles excuses. // Mais c'est pas pour ca que je l'utiliserai un jour }
Y'a un truc qui s'appelle la theorie des langages qui dit la choses suivante
Quel est le meilleur mixte entre un langage possedant beaucoup de termes et un langage faisant les phrases les plus longues (car peut de mot)
Eh bien la reponse est ... 2.718 mots
Autrement dit, la multiplication des notions nuit a la comprehension.
Donc comme une notion comme enum existe et peut etre remplacee...
Je vous conseille ... De ne pas l'utiliser ... Car c'est un truc probablement marginal
En gros, c'est mon avis,moins vous utilisez de type d'instruction, mieux vous comprendrez vos programmes ...
Excusez moi ... je m'emporte
Ouh là quel tissu d'âneries.
Je crois que tu n'aurais pas dû te vexer de la remarque d'Emmanuel. Si tu ne savais pas ce qu'était qu'un enum et à quoi ça servait (et apparemment tu ne le sais toujours pas), tu n'aurais pas dû apporter de réponse.
cf règle 4.12 du forum
Il faut parfois faire profil bas plutôt que de s'emporter.Citation:
Par contre vous n'êtes pas les bienvenus pour vous mêler de tout, donner votre avis sans aucun intérêt sur des domaines que vous ne connaissez pas, relayer les délires de [certains] professeurs, nous polluer la vie avec des langages de programmation dont tous le monde se fiche, donner votre avis sur des langages ou des outils que vous ne connaissez pas, nous donner des ordres sur la façon de gérer le forum ou le site, etc.
C'est très pratique pour définir des codes d'erreur. Et puis, il s'agit de la méthode recommandée pour définir des constantes entières.
Là, je vois pas trop ce que tu veux dire...
Il ne faut tout de même pas raconter n'importe quoi. Et la gestion des erreurs (Ce n'est pas la seule utilité des énumérations)?
En ce qui concerne la multiplication des notions, le langage C est un langage très compact, mais très pointu. Certains disent que c'est un langage réservés aux spécialistes. Si tu peux te passer d'énumérations dans tes programmes d'une centaine de lignes, dans les miens je n'y arrive pas. Personne ne t'oblige à utiliser des énumérations, mais de là à conseiller de ne pas les utiliser...
Thierry
Je sais pas ...
Donnez un exemple
Ou vous utilisez cette merveille
Ok
Le shell ... c pas mon truc...
Mais ce que tu ecris ...
C'est l'enumeration des enum dans ton code me semble t il
Autrement dit par convention ... les enum definissent des codes d'erreur chez toi.
C'est une convention ...
Pratique pour la recherche des erreurs dans votre code?
Je reconnais ... que la gestion des erreurs est compliquee
Mais que mets tu au bout de l'erreur citee plus haut ...
Je ne comprends pas
Y'a t il un message ?
En résumé, il re dis que dans la totalité de ses .h se trouvent 732 déclas d'enum.
Nombre qu'il serait bon de ponderer avec un nombre de .h, mais qui reste imposant.
Personnellement, je n'utilise que très rarement les enum, mais c'est plus par lubie personnelle qu'autre chose.
C'est un type particulièrement interressant dans bien des cas, erreur certes, mais aussi switch, etc.
On a assez polemiqué.
Pour le switch je peux comprendre ...
L'elegance veut qu'on prefere
case couleur_rouge
à case 26
si le c
permet de faire un truc du style
enum couleur {rouge ,vert , bleu }
...
Ensemble de couleur
et de faire un case
avec
case couleur ... // signifiant rouge vert ou bleu
Ca c'est royal
Alors oui , il est clair que enum , c'est du costaud ...
J'ai tord , et je la ramenerai plus ... sur enum
Et peut etre meme que je m'en servirai
Plus costaud que cela encore. J'imagine que tu utilises des #define dans ton code, n'est-ce pas ? On peut voir les enums comme des define ameliores, avec notamment trois proprietes interessantes:Citation:
Envoyé par e_gaillard37
- les valeurs sont attribuees automatiquement (mais restent personnalisables s'il le faut);
- les constantes enumerees ont le type int;
- les constantes enumerees respectent les portees de bloc.
L'un des usages que je prefere est de definir des identificateurs internes associe a des messages (ou a tout autre chose):
avec le fichier messages.txt:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 ... #define MESSAGE(id, ms) ID_##id, typedef enum { #include "messages.txt" NB_MESSAGE } t_ids; #undef MESSAGE ... #define MESSAGE(id, ms) ms, char const *message[] = { #include "messages.txt" }; #undef MESSAGE
Citation:
MESSAGE(ONE, "This is the first message.")
MESSAGE(TWO, "This is the second message.")
Bon tu definis ta macro...
tu remplis ton brave fichier message .txt
dans ton code
tu mets quoi ?
ch ... chaine.
tu as ton erreur...
La je comprends rien.Code:
1
2 if (err) message( ten, ch ) ??
L'idee est d'associer des messages a des identificateurs internes automatiquement. Ca peut servir a traiter des erreurs, des messages d'information, ... Il est tres simple d'ajouter un message, sans avoir a penser a ajouter un identificateur et a augmenter le nombre maximum d'identificateurs.
J'ai lu un des exemples cités
enum permet en fait. de remplacer une serie de chiffre
par des constantes symboliques en affectant une valeur a cette serie de constante
donc par defautCode:enum fruits { BANANE, ORANGE, POMME, FRAISE, KIWI };
BANANE vaut 0
ORANGE vaut 1
...
Vous me dites avec l'enrichissement d'un fichier externe on arrive a definir en fait a remplacer BANANE par "banane".
Tres bien ... Pour une seule colonne ... la designation ...
Cela ne presente pas d'interet
...Code:
1
2 #define BANANE "banane" #define ORANGE "orange"
a le meme effet
Il est clair qu'a partir de 2 colonnes c'est bien.
Mais un peu hardu non ?
Utilison des define
... structure de fichier en colonne ... Comme l'autreCode:
1
2 #define BANANE "banane","100 grammes" #define ORANGE "orange","25 grammes"
La methode citee dans l'exemple permet de faire un truc du style
"banane", "100 grammes"... Ce que peut faire aussi le define je viens de le verifier
Mais "100 grammes","banane" ... la le define semble etre out
ainsi que pour ignorer une colonne
Mais il en a sous la semelle
Ca compile ...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #define BANANE "banane","100 grammes" #define ORANGE "orange","25 grammes" ... // le fichier inclu contenant les define #define solo_poids(fruit,poids) poids // la macro ci dessus permet sans doute de ne voir que certaines // colonnes et ds un ordre désire void poids_du_fruit(char * fruit,char * ch) // fonction contenant structure complete { char ch1[100]; strcpy(ch1,solo_poids(fruit,ch)); .... } int main( int argc, char ** argv ) { poids_du_fruit(BANANE); // on ne passe que la constante symbolique poids_du_fruit(ORANGE); // on peut donc definir des fonction quelconques }
Pas besoins de definir enum ... on met nos define ds le fichier inclus
La victoire de enum... sur define est pas ecrasante pour l'exemple cite
... Pas eu besoin d'enumerer BANANE,ORANGE....
Quelle est la solution la plus elegante ?
La solution enum a t elle un avantage ?
Par contre , linitialisation à 0,1,2... ca c'est valable c sur.. pour la clarté d'un programme, c'est une evidence. On a juste a definir le nom dans le enum.
Outre le fait qu'appeller une fonction a deux parametres avec un seul parametre n'est pas a mon sens tres naturel ni tres lisible, une telle methode n'est applicable que pour l'appel de fonction.
En effet, tu ne peux pas, par exemple, affecter l'identifiant a une variable (quel en serait le type ? XXXX = "banane","100 grammes" ne sera pas correct), tu ne peux pas utiliser ces identifiant dans un switch() ... case, etc.
Bref cette methode qui ressemble plus a du bricolage qu'autre chose ne peut pas fournir les memes avantage qu'une construction a base de enum.
OK pour les switch ... j'ai ete clair la dessus.
Mais personne n'a ete capable de me confirmer si le case s'applique a chaque constante de l'ensemble ecrites une par une ...
en ecrivant
case bleu, blanc ,rouge
ou si on peut aussi l'appliquer a l'ensemble
case couleur_du_drapeau_francais
Le second cas serait un truc valable
mais bon ... si le truc cite plus haut existe pas
Ca definit des ensembles avec de valeurs par defaut croissante ... c'est extra
Si dans l'enum on met a la fin fin_de_tableau
Partout on peut utiliser
Code:
1
2
3
4
5 for (i=0;i<fin_de_tableau;i++) { ... on sait qu'on teste notre enumeration sans se poser la question de savoir ... si on les a initialisé au contraire d'une serie de define }
Pour le bricolage ...
Tes propos n'engagent que toi
Va voir l'exemple ... Tu me diras si en 5 mn t'as compris ... Il n'est pas impossible que ce soit bien compliqué. Et peut être qu'ils utilisent ... Les memes artifices pour recuperer une colonne.
Concernant les fichier inclus et leur traitement
Et le but reste le meme ... faire un truc du style erreur(CONSTANTE_SYMBOLIQUE)
Si, il y a une incoherence dans le fichier... Le programme ne compilera pas
De la meme facon ... Pour l'autre méthode
Mais bon... Il est pas impossible desormais que je sache ce qu'est enum.
Merci les gars ... et j'espere pas avoir embete mon monde
Non ce n'est pas possible.Citation:
Mais personne n'a ete capable de me confirmer si le case s'applique a chaque constante de l'ensemble ecrites une par une ...
en ecrivant
case bleu, blanc ,rouge
ou si on peut aussi l'appliquer a l'ensemble
case couleur_du_drapeau_francais
Bof! Le but d'enum est de faire des énumérations finies sur lesquelles on puisse faire des discriminations. Je ne vois pas l'intérêt de traiter les éléments d'une énumération de la même façon. Couramment, tu utilises switch sur un seul type d'énumération.Citation:
Le second cas serait un truc valable
Oui, ça peut être une utilisation intéressante des enums mais pas forcément classique. Cette façon de faire me fait penser à l'indexation des tableaux en ADA.Citation:
mais bon ... si le truc cite plus haut existe pas
Ca definit des ensembles avec de valeurs par defaut croissante ... c'est extra
Si dans l'enum on met a la fin fin_de_tableau
Partout on peut utiliser
Code:
1
2
3
4
5 for (i=0;i<fin_de_tableau;i++) { ... on sait qu'on teste notre enumeration sans se poser la question de savoir ... si on les a initialisé au contraire d'une serie de define }
C'était du bricolage. Tu dois écrire quelque chose de lisible et compréhensible et non pas user d'astuces obscures.Citation:
Pour le bricolage ...
Tes propos n'engagent que toi
Va voir l'exemple ... Tu me diras si en 5 mn t'as compris ... Il n'est pas impossible que ce soit bien compliqué. Et peut être qu'ils utilisent ... Les memes artifices pour recuperer une colonne.
Complètement si. Penche toi sur un livre de C avant d'affabuler.Citation:
Concernant les fichier inclus et leur traitement
Et le but reste le meme ... faire un truc du style erreur(CONSTANTE_SYMBOLIQUE)
Si, il y a une incoherence dans le fichier... Le programme ne compilera pas
De la meme facon ... Pour l'autre méthode
Mais bon... Il est pas impossible desormais que je sache ce qu'est enum.
Merci les gars ... et j'espere pas avoir embete mon monde
Merci aussi d'utiliser les balises CODE. Je ne sais pas combien de fois on te l'aura dit. C'est aussi pour gagner en lisibilité.
Quel exemple ?
Le tien ? Oui ca se comprends car il est limite au strict minimum permettant de presenter le principe.
Dans un source complet, j'en suis moins certain (surtout a cause du nombre de parametres reels diferent du nombre de parametres apparents).
Celui d'Emmanuel ou de DaZumba ? Oui ca se comprends assez rapidement (enfin bien sur si on conait un minimum les macros et le fonctionnement de # et ##, mais bon ca reste quand meme assez basique).
Quels artifices utilises pour recuperer une colonne te choque ? Definir une macro ? Mais ce n'est pas ca qui me gene dans ton principe.
Non ce n'est pas le but, c'est un des buts. On peut l'utiliser effectivement pour la gestion d'erreur, mais ca ne se limite pas a ca.
Ce qui est plutot une bonne chose. Je prefere largement un programme qui ne compile pas du tout a un programme qui compile et qui semble marcher jusqu'au jour ou ...
Salut,
Il est vrai que, si on regarde de manière purement superficielle, l'utilisation d'un enum revient *à peu près* à l'utilisation de plusieurs #define.
Mais c'est tirer des conclusions un peu hâtives.
Un #define est une instruction préprocesseur.
Le résultat est que quand tu lance ta compilation, le préprocesseur va parcourir le fichier d'en-tête, voir que tu définit BANANE, FRAISE, FRAMBOISE et tous les autres à une valeur "unique", et, chaque fois qu'il rencontrera l'un de ces termes, il ne se posera pas la question: il remplacera le terme par la valeur que tu lui a donnée... Sans s'inquiéter de savoir s'il y a la moindre logique, à un moment donné, de remplacer le terme par la valeur.
Cela signifie que, si tu a fournis une valeur numérique entière pour tes #define tu n'aura pas de vérification quant au fait de savoir si le remplacement de BANANE par l'entier fournis est "cohérente" avec le reste du code qui l'entoure...
Par contre, les valeurs énumérées sont d'office et obligatoirement de type entier.
Le résultat en est que, si, pour une raison qui ne tient qu'à toi, en cours de développement, tu vient à décider de remplacer la valeur de ton #define BANANE par autre chose (une chaîne de caractères ou un réel) tu auras (ou si tu préfère, tu peux avoir) l'impression de pouvoir le faire "sans risque"... mais la prochaine compilation te sortira des erreurs en pagaille.
Par contre, dans le cadre d'un enum, non seulement les valeurs énumérées sont groupées, avec tous les avantage que cela peut te conférer, mais en plus, tu sais que si tu veux changer la valeur d'un des éléments, la nouvelle valeur ne pourra en tout cas être que... un nouvel entier.
PS Pense à utiliser la balise [ CODE ] [ /CODE ] (sans les espaces) pour entourer les exemples de code dans tes message (le bout "#" au dessus du formulaire fait pareil), plein d'avantages pour tout le monde sont à la clé ;)
Personnellement, et pour ajouter mon grain de sel, j'utilise beaucoup les enum, et surtout pour faire mes propres types et expliciter mon code.
Par exemple, un jeu de 32 cartes, voyons les enum qu'on peut définir :
Mes champs de bits ne sont ps nécessaire mais c'est pour limiter la taille, car un enum prenant par défaut 4 octets, pour 4 ou 8 valeurs c'est beaucoup je trouve...Code:
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 // Pour les valeurs de cartes : typedef enum PSYValue_tag { Sept = 0, Huit, Neuf, Dix, Valet, Dame, Roi, As } PSYValue; // Pour les couleurs des cartes : typedef enum PSYSuit_tag { Pic = 1, Coeur, Carreau, Trefle } PSYSuit; // Pour définir une carte : typedef struct PSYCard_tag { PSYSuit suit:4; PSYValue value:4; } PSYCard;
Bon continuons nos investigations. Par exemple, je vais définir un tableau de chaînes de caractères pour contenir les noms de mes variables :
Et maintenant... Comment affiche-je le nom d'une carte ? Imaginons que nous avons une carte prédéfinie :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 static const char * const CardsName[] = { "Sept", "Huit", "Neuf", "Dix", "Valet", "Dame", "Roi", "As" }; static const char * const CardsSuit[] = { "None", "Pic", "Coeur", "Carreau", "Trefle" };
En console, nous verrons donc affiché :Code:
1
2
3
4
5
6 // Quelque part dans le code : PSYCard maCarte = {Pic, Valet}; // par exemple // plus loin pour afficher : printf("Ma carte : %s de %s.\n", CardsName[maCarte.value], CardsSuit[maCarte.suit])
Ma carte : Valet de Pic.
Personnellement, je trouve ce système génial... Mais ça n'engage que moi...
Ah on peut aussi faire un switch par exemple :
Bien sûr, ici ce switch est inutile puisque les tableaux de valeurs peuvent nous faciliter l'écriture de la phrase. Cependant, on peut déjà entrevoir les possibilités que nous offre le enum.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 switch(premiereCartePosee.suit) { case Pic : printf("Pic demandé !\n"); break; case Coeur : printf("Coeur demandé !\n"); break; case Carreau : printf("Carreau demandé !\n"); break; case Trefle : printf("Trefle demandé !\n"); break; default : printf("ERREUR !\n"); break; }
Donc, l'enum crée un nouveau type d'entier, et peut donc être utilisé partout où les entiers sont utilisés. C'est-à-dire qu'on peut remplacer un "int" ou "unsigned int" ou "short", etc. par enum monEnum et remplacé la valeur par l'une des valeurs définies dans l'enum...
Merci, pour avoir expose vos divers points de vue.