21

The language designers have chosen to make the curly braces in the following scenarios optional:

if (a)
    b
while (a)
    b
...

Why is the same not allowed in functions, like this?

int add(int a, int b)
    return a + b;
Overv
  • 8,433
  • 2
  • 40
  • 70
  • Maybe coz a function must know what its body contains specifically . – Afaq Oct 23 '12 at 15:52
  • Regardless of a function or conditional/looping construct the length and contents of the body must be known at compile time so the curly braces are just ways of organizing the instructions. – sean Oct 23 '12 at 15:56
  • 2
    answers to this questions are almost guaranteed to be speculative. pretty sure this is off topic. – Colin D Oct 23 '12 at 16:02
  • A perfectly legitimate question with a factual answer and a massive amount of upvotes for speculative guesses. Great. – djechlin Oct 23 '12 at 16:07
  • 1
    Related: http://stackoverflow.com/questions/6016654/why-do-methods-with-only-one-statement-need-braces – P.P Oct 23 '12 at 16:16

6 Answers6

30

I'm sure this would mess up the grammar. For example there would be no difference between this empty function definition...

void empty()
{
    ;
}

...and this function declaration:

void empty();
Albzi
  • 15,431
  • 6
  • 46
  • 63
Robert Cooper
  • 1,270
  • 9
  • 11
6

I'm not sure that they did "choose" this. Rather, the ability ommit curly braces for if, while, for, etc. emerges as a natural consequence of the way they specified the grammar. The grammer forbids it for functions probably because of the old-style function declarations.

Peter Ruderman
  • 12,241
  • 1
  • 36
  • 58
3

There is no fixed keyword related to function definitions. With if/else/for/while/switch there is one such keyword that marks the beginning of the logic-control structure.

Even though context allows us humans to discern how come int some_name (some_expression) some_other_expressions; is a function - in programming practice (although doable unambiguously) it takes a lot of backtracking to make sure 3-4-6 symbols ahead in the token-stream nothing changes this from a function declaration to something else.

A programming language parser can be classified by it's approach to parsing, either it takes the current token in the token list and checks if the next token confirms "this is an if" or "this is a function" or it takes a maximum look-ahead tokens (2-3-6?) and confirms "this could be a function", "now that i see the 5th token this is surely a function" or it uses backtracking with a variable look-ahead approach that goes as far ahead in the token list as needed to make sure the construct we are studying is something not something else.

Mihai Stancu
  • 15,848
  • 2
  • 33
  • 51
2

If I were to speculate, I'd say that it's because a function normally contains more than one statement whereas an if or while statement often contains only one statement. Also, it proved to be long-sighted inasmuch as in C++ allowing the ommission of {} would lead to ambiguities in member functions. For example:

struct s
{
     void f() const int i; //does const refer to int i or the function?
}
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • So what does that declaration actually do? – djechlin Oct 23 '12 at 16:06
  • @djechlin: It results in a compiler error because {} are not optional for functions. My point was that if they were, it would lead to ambiguities in C++. Robert Cooper's answer shows that it would cause ambiguities in C as well. – Armen Tsirunyan Oct 23 '12 at 16:09
2

I know this is like, a 7 year bump, but all of the above answers are incorrect; though Robert Cooper is right when he says it would break the grammar.

The real problem has to do with how the original version of C looked:

main(argc, argv)
    char *argv[];
{
    puts("hello world!");
}

Everything in C was an int by default, so much of the type annotation could be omitted. Modern C is fully backwards compatible with this because people didn't want to throw out or update a bunch of existing code.

Note that the type annotation that comes after the function parameter list looks exactly like a normal variable declaration. This was done intentionally, probably to simplify the original grammar, but would mean that trying to define a function without curly braces like in your example would be completely ambiguous.

Basically, it can't work because, the parser can't tell the difference between a declaration statement and type annotation.

Waji Deus
  • 39
  • 3
1

Curly braces are not optional components of the "if" and "if-else" control statements. The grammatical production for the "if" control statement allows one nonterminal symbol to follow the expression. The grammatical production for the "if-else" control statement allows one nonterminal symbol to follow the expression and one nonterminal symbol to follow the "else" terminal symbol. The name of that nonterminal symbol is <statement>.

In the context of the control structures (a.k.a. control statements), the curly braces belong to a language nonterminal symbol known as <compound-statement> (sometimes referred to as <block>). The non-terminal symbol <compound-statement> appears on the right-hand side of the <statement> grammatical production, which is why the curly braces can be used with the "if" and "if-else" control statements (i.e., a compound statement is a statement).

<statement> ::= <if-then-statement> | 
                <if-then-else-statement> | 
                <for-statement> |
                <do-while-statement> |
                ...
                <compound-statement>

<statement-list> ::=  <statement> | <statement-list> <statement> 

<if-then-statement> ::= "if" "(" <expression> ")" <statement> 

<if-then-else statement> ::= "if" "(" <expression> ")" <statement> 'else' <statement>

<compound-statement> ::= "{" <statement-list> "}"

With respect to function declarations, the <compound-statement> nonterminal symbol is the last nonterminal symbol on the right-hand side of the <function-declaration> grammatical production.

P.S. All nonterminal symbols are grammatical productions. All grammatical productions reduce to one or more nonterminal and/or terminal symbols. Terminal symbols are language keywords.

bit-twiddler
  • 111
  • 4