If you look at the C syntax, there are a number of contexts that require a statement, a term that's defined by the grammar itself.
In any of those contexts, one of the forms of statement you can use is a compound-statement, which consists of an opening brace {
, a sequence of zero or more declarations and/or statements, and a closing brace }
. (In C89, all declarations in a compound-statement must precede all statements; C99 removed that restriction.)
A function-definition specifically requires a compound-statement, not just any kind of statement. (I'm fairly sure that's the only case where a compound-statement is the only kind of statement you can use). If not for that restriction, you'd be able to write:
void say_hello(void) printf("Hello, World!\n");
But since most function definitions contain multiple declarations and/or statements, there wouldn't be much advantage in permitting that.
There's a separate question: when should you omit braces. In my personal opinion, the answer is "hardly ever". This:
if (condition)
statement;
is perfectly legal, but this:
if (condition) {
statement;
}
IMHO reads better and is easier to maintain (if I want to add a second statement, the braces are already there). It's a habit I picked up from Perl, which requires braces in all such cases.
The only time I'll omit the braces is when an entire if statement or something similar fits on a single line, and doing so makes the code easier to read, and I'm unlikely to want to add more statements to each if
:
if (cond1) puts("cond1");
if (cond2) puts("cond2");
if (cond3) puts("cond3");
/* ... */
I find such cases are fairly rare. And even then, I'd still consider adding the braces anyway:
if (cond1) { puts("cond1"); }
if (cond2) { puts("cond2"); }
if (cond3) { puts("cond3"); }
/* ... */