Hello,
L'outil d'analyse de code d'Eclipse CDT râle quand dans un switch, je ne mets pas de break dans la clause default.
Que dit la norme ?
Hello,
L'outil d'analyse de code d'Eclipse CDT râle quand dans un switch, je ne mets pas de break dans la clause default.
Que dit la norme ?
Salut.
Vu qu'on peut ne pas en mettre dans les case, ce serait étonnait qu'il soit obligatoire de le faire pour default...
Et puis il me semble qu'elle doit être mise à la fin (enfin je veux dire, ça n'a pas de sens de mettre des case après, si ?), alors il faudra qu'on m'explique l'intérêt de vouloir couper une structure de contrôle à la toute dernière instruction...
Ton outil d'analyse ne te demanderait pas de mettre des continue à la fin des boucles, par hasard ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 while (...) { (...) continue; }
Attention, il me génère un warning, pas une erreur. Et je pense qu'il le ferait également dans le cas d'un case, sauf s'il est vide.
C'est un usage, logique, mais y est-on vraiment obligé ?
On peut considérer que les case seront utilisés dans des cas exceptionnels, que dans la grande majorité des cas, on se retrouvera dans le default, et qu'alors, cela aurait un sens de le mettre au début.
Pour savoir ce que default doit traiter, doit-on déjà être passé par les case ?
D'après ce que j'ai compris, le résultat de l'expression du switch est comparé successivement avec la valeur de chaque case, dans l'ordre dans lequel ils sont écrits, jusqu'à arriver à une correspondance, la clause default, ou la fin du switch ... case.
C'est pour ça que je pense que ça n'a pas de sens de mettre des case après un default.
Ce serait comme écrire des instructions après un return (non conditionnel)...
Après, je peux me tromper.
Si tous les case sont passés en revue avant de passer à la clause default, alors la position de celle-ci n'a a priori pas vraiment d'importance...
le parcours du switch n'est pas lineaire mais en O(1), l'ordre importe peu.
http://codepad.org/95lH5ojF
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 #include <iostream> using namespace std; int main() { int i(4); switch(i) { case 1 : cout << "coin 1"; break; default: cout << "coin d"; break; case 0 : cout << "coin 0"; break; } }
J'ai vu du code qui faisait systématiquement ça : le default au début, puis les case ensuite. C'était souvent parce que le cas par défaut était le(s) cas OK alors que les case traitaient des cas d'erreur. C'est pas forcément ce qu'il y a de plus clair mais ça existe.
L'absence de break sur le dernier cas (que ce soit un default ou un case) est plus une erreur d'esthétique. Note que les règles de codage stipulent de mettre systématiquement un default et de mettre systématiquement un break. L'absence devant être justifiée dans le code pour montrer qu'il s'agit bien d'un cas souhaité et non d'un oubli.
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
Salut,
Il ne faut pas oublier, non plus, que, en cas d'absence de break, plusieurs cas peuvent etre exécutés successivement...
Cela peut etre souhaité (bien que non (ou du moins pas forcément) souhaitable) si les actions à effectuer dans un cas donné sont un "subset" du cas précédent, mais cela peut surtout apporter quelques soucis majeurs, dus, essentiellement à ce comportement particulier
Le dernier cas envisagé (default dans le cas présent
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 int main() { int i(1); switch (i) { case 1: std::cout<<"cas 1"<<std::endl; case 2: std::cout<<"cas 2"<<std::endl; break; case 3: std::cout<<"cas 3"<<std::endl; break; default : std::cout<<"cas par défaut"<<std::endl; } return 0; }) ne posera pas de problème... tant que l'on ne décidera pas de rajouter une valeur en dessus
cet avertissement fait sans doute preuve d'un excès de prévoyance, mais j'ai tendance à estimer que l'on n'est jamais assez paranoïaque dans une revue de code![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Ah ?
Personnellement, je trouve que c'est plus esthétique de ne pas le mettre...
À moins que ce soit ça l'erreur ?
Même si ça n'a pas de sens de mettre une clause « par défaut » ?
Je veux dire s'il y a un cas pour toutes les valeurs possibles de l'expression (énumération, caractère dont on sait que c'est un chiffre, etc.) ?
L'absence du default ou du break ?
Ben, le comportement ne changera pas, mais perso, je serais systématiquement surpris quand je verrai le dernier default/case du switch sans break.
Oui. C'est vrai que c'est parfois absurde car la clause default ne sera jamais atteinte. Ca donne un côté uniforme au code. Mais c'est probablement un reste de la programmation défensive.
L'absence du break. Mais d'une façon général, toute les non respects des règles. C'est tout simplement pour montrer que ce n'est pas une erreur de codage mais que c'est bien voulu.
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
Ok.
Je ne connaissais pas ces deux règles de codage.
Lorsque j'ai appris la structure switch ... case ..., j'avais retenu que l'on ne met que les cas qui nous intéressent ; et que par conséquent, on ne met de met de clause default que lorsque c'est nécessaire.
Par contre, pour l'absence de break pour le dernier cas, c'est juste moi qui trouvais inutile de mettre une instruction qui, finalement, ne fait rien...
Dorénavant, je respecterai ces règles à la lettre.
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 enum e_enum {UN, DEUX, TROIS}; e_enum x = (...); switch (x) { case UN: (...) break; case DEUX: (...) break; case TROIS: (...) break; default: throw std::runtime_error("Valeur illégale pour une énumération !!!"); // Il faut mettre un « break » ici aussi ? }
Celui qui t'a appris cela est... hummm, je vais rester gentil et poli
La meilleure preuve, c'est que, si tu règle le compilateur pour qu'il soit "paranoïaque", il t'enverra un avertissement si tous les cas d'une énumérations ne sont pas pris en compte, meme si tu sais que seules deux ou trois valeurs énumérées risquent d'être utilisés
Cela ne mange, en tout cas, pas de painPar contre, pour l'absence de break pour le dernier cas, c'est juste moi qui trouvais inutile de mettre une instruction qui, finalement, ne fait rien...
Dorénavant, je respecterai ces règles à la lettre.
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 enum e_enum {UN, DEUX, TROIS}; e_enum x = (...); switch (x) { case UN: (...) break; case DEUX: (...) break; case TROIS: (...) break; default: throw std::runtime_error("Valeur illégale pour une énumération !!!"); // Il faut mettre un « break » ici aussi ? }
L'avantage, c'est que si tu rajoute QUATRE et que, par distraction ou que sais-je, tu mets cette valeur après default, tu es sur qu'il n'y aura pas de problème (comprends : si d'aventure, default fait autre chose que lancer une exception)
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Salut,
Dans un cas comme ça, cela s'apparenterait probablement plus à une violation de contrat. Plutôt que de lever une exception, je ferais un assert
Ceci dit :
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 enum e_enum {UN, DEUX, TROIS}; e_enum x = (...); switch (x) { case UN: (...) break; case DEUX: (...) break; case TROIS: (...) break; default: assert(false); break; }
c'est un cas particulier où compilateur et outils de vérification de code peuvent râler pour indiquer un code non atteignable si tu mets un break. C'est le genre de cas très particulier pour indiquer qu'on ne mets pas de break pour cette raison :
ce qui pourrait être aussi être le cas dans des case
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 default: throw std::runtime_error("Valeur illégale pour une énumération !!!"); // Rule XX not followed : break unused since code is unreachable due to exception raising }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 switch(x) case E_1: return do_something(); // Rule XX not followed : break unused since code is unreachable due to return statement case E_2: ... }
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
les case sans break servent surtout a implanter un Duff's Device
Si j'ai :
le compilateur en râle pas, mais si j'ai :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 case 0 : case 1 : case 2 : instructions; break;
le compilateur râle parce que le case 1 n'a pas de break, alors que c'est voulu.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 case 0 : case 1 : instructions; case 2 : instructions; break;
Peut-on par exemple mettre un continue pour indiquer que c'est voulu ?
Cet ajout est-il neutre ?
Partager