Both kernel coding style and gnome's C style guide states that:
Do not unnecessarily use braces where a single statement will do.
if (condition)
action();
but at the same time it should be sometimes used, as in else
branch of:
if (condition) {
do_this();
do_that();
} else {
otherwise();
}
Is there any technical or usability reasons to prefer it this way? Are there any objective reasons not to put the braces there everytime?
There are only stylistic and ease-of-editing-related reasons.
Whether you omit the brace or not, C compilers must act as if the braces were there (+ a pair around the whole iteration statement (if
or if
-else
)).
6.8.4p3:
A selection statement is a block whose scope is a strict subset of the scope of its enclosing block. Each associated substatement is also a block whose scope is a strict subset of the scope of the selection statement.
The existence of these implicit blocks can be nicely demonstrated with enums:
#include <stdio.h>
int main()
{
enum{ e=0};
printf("%d\n", (int)e);
if(1) printf("%d\n", (sizeof(enum{e=1}),(int)e));
if(sizeof(enum{e=2})) printf("%d\n", (int)e);
printf("%d\n", (int)e);
//prints 0 1 2 0
}
A similar rule also exists for iteration statements: 6.8.5p5.
These implicit blocks also mean that a compound literal defined inside an iteration or selection statement is limited to such an implicit block. That is why example http://port70.net/~nsz/c/c11/n1570.html#6.5.2.5p15 from the standard puts a compound literal in between a label an explicit goto
instead of simply using a while
statement, which would limit the scope of the literal, regardless of whether or not explicit braces were used.
While it may be tempting, don't ever do:
if (Ptr) Ptr = &(type){0}; //WRONG way to provide a default for Ptr
The above leads to UB (and actually nonworking wit gcc -O3
) because of the scoping rules.
The correct way to do the above is either with:
type default_val = {0};
if (Ptr) Ptr = &default_val; //OK
or with:
Ptr = Ptr ? Ptr : &(type){0}; //OK
These implicit blocks are new in C99 and the inner ones (for selection statements (=ifs)) are well rationalized (C99RationaleV5.10.pdf, section 6.8) as aids in refactoring, preventing braces that are added from previously unbraced branches from changing meaning.
The outermost branch around the whole selection statements doesn't appear to be so well rationalized, unfortunately (more accurately, it's not rationalized at all). It appears copied from the rule for iterations statements, which appears to copy the C++ rules where for
-loop-local variables are destructed at the very end of the whole for loop (as if the for loop were braced).
(Unfortunately, I think that for selection statement the outermost implicit {} does more harm than good as it prevents you from having macros that stack-allocate in just the scope of the caller but also need a check, because then you can only check such macros with ?:
but not with if
, which is weird.)
Well, there's one special case in which braces do need to be used: Suppose you have the following code:
if (a)
if (b)
f();
else g();
As it is indented, one could assume the else g();
statement belongs to the first if(a)
statement, but C syntax rules say that it is interpreted as (now with braces):
if (a) {
if (b) {
f();
}
else {
g();
}
}
which actually means:
if (a) {
if (b) {
f();
}
else {
g();
}
}
in case you wanted the other possibility, then you must use braces. For example you can write it this way:
if (a) {
if (b)
f();
}
else
g();
which actually means:
if (a) {
if (b) {
f();
}
}
else {
g();
}
As all elementary programming books recommend: If you are in doubt about operator precedence, then use parentheses; if you extend that to statements coding, if you are in doubt, use braces! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With