Quand puis-je omettre les accolades en C?

Je suis presque certain que cela a déjà été demandé, mais je ne trouve aucune réponse.

Quand puis-je omettre les accolades en C? J’ai déjà vu des déclarations de return accolade, telles que

 if (condition) return 5; 

Mais cela ne semble pas toujours fonctionner pour toutes les déclarations, c’est-à-dire lors de la déclaration d’une méthode.

éditer :

Les règles relatives à l’omission des accolades sont-elles les mêmes qu’en Java?

Les seuls endroits où vous pouvez omettre les crochets concernent les corps d’instructions if if-else , for , while ou do-while si le corps est constitué d’une seule instruction:

 if (cond) do_something(); for (;;) do_something(); while(condition) do_something(); do do_something(); while(condition); 

Toutefois, notez que chacun des exemples ci-dessus compte comme une instruction unique selon la grammaire; cela signifie que vous pouvez écrire quelque chose comme

 if (cond1) if (cond2) do_something(); 

C’est parfaitement légal. if (cond2) do_something(); réduit à une seule déclaration. Donc, d’ailleurs, fait if (cond1) if (cond2) do_something(); , afin que vous puissiez descendre plus loin dans la folie avec quelque chose comme

 for (i=0; i < N; i++) if (cond1) if (cond2) while (cond3) for (j=0; j < M; j++) do_something(); 

Ne fais pas ça.

Si vous regardez la syntaxe C, il existe un certain nombre de contextes qui nécessitent une instruction , un terme défini par la grammaire elle-même.

Dans l’un de ces contextes, l’une des formes d’instruction que vous pouvez utiliser est une instruction composée, qui consiste en une accolade ouvrante { , une séquence de zéro ou plusieurs déclarations et / ou instructions et une accolade fermante } . (En C90, toutes les déclarations d’une instruction composée doivent précéder toutes les instructions; C99 a supprimé cette ressortingction.)

Une définition de fonction nécessite spécifiquement une instruction composée , pas n’importe quel type d’instruction. (Je pense que c’est le seul cas où une déclaration composée est le seul type de déclaration que vous pouvez utiliser). Sinon pour cette ressortingction, vous seriez capable d’écrire:

 void say_hello(void) printf("Hello, world\n"); 

Mais comme la plupart des définitions de fonctions contiennent plusieurs déclarations et / ou instructions, cela ne présente aucun avantage.

Il y a une question distincte: quand faut- il omettre les accolades. À mon avis, la réponse est “presque jamais”. Ce:

 if (condition) statement; 

est parfaitement légal, mais ceci:

 if (condition) { statement; } 

IMHO lit mieux et est plus facile à maintenir (si je veux append une deuxième déclaration, les accolades sont déjà là). C’est une habitude que j’ai apprise auprès de Perl, qui exige des accolades dans tous les cas.

La seule fois où je vais omettre les accolades, c’est quand une déclaration if entière ou quelque chose de similaire s’adapte à une seule ligne, ce qui facilite la lecture du code et il est peu probable que je veuille append plus d’instructions à chacune d’elles if :

 if (cond1) puts("cond1"); if (cond2) puts("cond2"); if (cond3) puts("cond3"); /* ... */ 

Je trouve que de tels cas sont assez rares. Et même dans ce cas, je songerais quand même à append les accolades:

 if (cond1) { puts("cond1"); } if (cond2) { puts("cond2"); } if (cond3) { puts("cond3"); } /* ... */ 

Mais cela ne semble pas toujours fonctionner pour toutes les déclarations.

Plus précisément? Lorsqu’une seule déclaration est attendue, elle est parfaitement valide. Les boucles, l’instruction if , etc. s’attendent toutes à une instruction et c’est soit un bloc, soit une instruction unique qui n’est pas enfermée dans un bloc.

Un exemple:

 int a[2][2] = {{1, 2}, {3, 4}}; 

vous pouvez utiliser le formulaire équivalent valide:

 int a[2][2] = {1, 2, 3, 4}; 

Certains compilateurs verbeux peuvent avertir, mais c’est valide.

Notez que pour l’instruction if (idem pour le while , l’instruction for , …), les {} ne sont pas omis. Ils ne sont tout simplement pas demandés. L’instruction if a cette syntaxe:

if (expression) statement

Si vous voulez une instruction multiple au lieu d’une seule instruction, vous pouvez utiliser une instruction composée entourée {} .

Vous avez principalement besoin d’accolades lorsque vous souhaitez combiner plusieurs instructions ou expressions en une seule, par exemple:

 { x = 1; y = 2; } 

Donc, si vous mettez ce qui précède sous if ou else le tout dans les accolades sera exécuté dans son ensemble, alors que si vous omettez les accolades, seul le premier ( x = 1; dans ce cas) sera utilisé dans le cadre de if ou else .

Vous les utilisez aussi généralement avec switch() :

 switch (x) { case 1: // do smth break; case 2: // do smth else break; } 

Vous en avez généralement besoin avec l’instruction do-while :

 do { printf("%d\n", x); x++; } while (x < 10); 

Vous en avez besoin avec les compilateurs C89 lorsque vous souhaitez définir et utiliser une variable temporaire au milieu du code:

 int main(void) { puts("Hello World!"); { int x; for (x = 0; x < 10; x++) printf("%d\n", x); } return 0; } 

Vous les utilisez pour commencer et terminer le corps d'une fonction, une définition de structure / union, une définition d'énumération, l'initialisation d'une structure / union / tableau, par exemple:

 void blah(void) { } enum e { e1 = 1, e2 = 2 }; struct s { int foo; int bar; } s = { 1, 2 }; int a[3] = { 1, 2, 3 }; 

Vous pouvez les omettre parfois lors d'initialisations, par exemple:

 char str2[] = { "abc" }; char str1[] = "abc"; 

Chaque fois qu’il y a un bloc avec plus d’une ligne (comptant les lignes comme une seule instruction avec un;)

Exemples:

 for (i = 0; i < j; i++ ) foo(i); while (1) foo(); if( bool ) foo(); void cheese() printf("CHEESE"); 

Tout après le; dans les lignes ci-dessus ne compte pas comme "à l'intérieur" du bloc comme s'il y avait {}.

Vous pouvez les omettre quand vous exécutez une seule instruction:

 for(...) printf("brackets can be omited here"); if(...) printf("brackets can be omited here"); else printf("brackets can be omited here too"); 

etc. Vous pouvez toujours les append, cela ne fait jamais de mal et aide à clarifier la scope, mais vous êtes assez en sécurité. Le seul “piège” auquel je puisse penser est si vous essayez de faire une déclaration dans ce domaine (ce qui est inutile en passant):

 if(...) int a = 5; 

Cela provoquera une erreur, mais c’est parce que vous pouvez effectuer une seule instruction sans accolades, pas une déclaration . Distinction importante.

Techniquement, vous pouvez même effectuer plusieurs opérations sans crochets s’ils sont concaténés avec l’opérateur, … pas que je conseille de le faire, mais qu’il est utile de le noter:

 if(...) value++, printf("updated value with brackets"); 

Et pour votre édition, vous pouvez voir dans la spécification Java que les règles sont les mêmes. J’ai lié spécifiquement à la section if , mais vous pouvez voir ensuite if une déclaration est attendue, vous pouvez ainsi ignorer les accolades.

En cas de doute, utilisez des accolades. Ils ne “coûtent” aucun supplément [sauf si vous les utilisez de manière incorrecte].

Une règle assez basique est “si vous avez plus d’un point-virgule à la même indentation, vous devriez avoir des accolades”. Ce n’est pas tout à fait aussi simple, mais il s’agit d’une phrase «sans aucune complication».

Et oui, Java étant basé sur la syntaxe C, il a les mêmes règles fondamentales – il existe peut-être une certaine bizarrerie où Java est différent du C ou C ++, mais ce sont des choses inhabituelles / étranges, que vous ne feriez pas normalement en écrivant du code typique Je n’ai pas fait beaucoup de java, donc je ne peux pas dire que j’en ai trouvé, mais je suis presque sûr qu’il y a QUELQUES différences – ce sont des langues différentes, après tout].

Ce qui suit semble un peu délicat:

 if (...) printf("I'm conditional\n"); 

Je suppose que le préprocesseur prend en charge les lignes vides, donc cette déclaration est correcte. Très mauvaise pratique bien sûr.