41

When I tried the following code I get the error mentioned.

if(a==1)
  int b =10;

But the following is syntactically correct

if(a==1)
{
   int b = 10;
}

Why is this?

Richard
  • 8,961
  • 3
  • 38
  • 47
MsPillai
  • 568
  • 1
  • 4
  • 7
  • Post your error. Your code is good to go unless you are accessing "b" out of scope. – Abhineet Mar 15 '14 at 05:13
  • I have mentioned the error in the title. Also, even if b is not being used anywhere else in the code, the error still comes up. – MsPillai Mar 15 '14 at 05:17
  • Also, there are some differences between C and C++ which is best resolved by directly going to the documentation. Review my [answer](http://stackoverflow.com/a/30148183/307454) wrt the `while` loop wherein I wrestled with the same compile error. – lifebalance May 10 '15 at 18:27

3 Answers3

73

This is actually a fairly interesting question. It's not as simple as it looks at first. For reference, I'm going to be basing this off of the latest C11 language grammar defined in N1570

I guess the counter-intuitive part of the question is: if this is correct C:

if (a == 1) {
  int b = 10;
}

then why is this not also correct C?

if (a == 1)
  int b = 10;

I mean, a one-line conditional if statement should be fine either with or without braces, right?

The answer lies in the grammar of the if statement, as defined by the C standard. The relevant parts of the grammar I've quoted below. Succinctly: the int b = 10 line is a declaration, not a statement, and the grammar for the if statement requires a statement after the conditional that it's testing. But if you enclose the declaration in braces, it becomes a statement and everything's well.

And just for the sake of answering the question completely -- this has nothing to do with scope. The b variable that exists inside that scope will be inaccessible from outside of it, but the program is still syntactically correct. Strictly speaking, the compiler shouldn't throw an error on it. Of course, you should be building with -Wall -Werror anyways ;-)

(6.7) declaration:
            declaration-specifiers init-declarator-listopt ;
            static_assert-declaration

(6.7) init-declarator-list:
            init-declarator
            init-declarator-list , init-declarator

(6.7) init-declarator:
            declarator
            declarator = initializer

(6.8) statement:
            labeled-statement
            compound-statement
            expression-statement
            selection-statement
            iteration-statement
            jump-statement

(6.8.2) compound-statement:
            { block-item-listopt }

(6.8.4) selection-statement:
            if ( expression ) statement
            if ( expression ) statement else statement
            switch ( expression ) statement
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
sheu
  • 5,653
  • 17
  • 32
  • Also, there are some differences between C and C++ which is best resolved by directly going to the documentation. Review my [answer](http://stackoverflow.com/a/30148183/307454) wrt the `while` loop wherein I wrestled with the same compile error. – lifebalance May 10 '15 at 18:28
  • The errors from this answer and yours are not exactly equivalent. This answer deals with the body of the control flow statement (the *statement* part of `if ( expression ) statement`), whereas yours deals with its control *expression*. In the case of this answer, the C and C++ grammars are identical. – sheu May 13 '15 at 19:07
1

{ } -->

defines scope, so if(a==1) { int b = 10; } says, you are defining int b, for {}- this scope. For

if(a==1)
  int b =10;

there is no scope. And you will not be able to use b anywhere.

Pranit Kothari
  • 9,721
  • 10
  • 61
  • 137
-4

By C89, variable can only be defined at the top of a block.

if (a == 1)
    int b = 10;   // it's just a statement, syntacitially error 

if (a == 1)
{                  // refer to the beginning of a local block 
    int b = 10;    // at the top of the local block, syntacitially correct
}                  // refer to the end of a local block

if (a == 1)
{
    func();
    int b = 10;    // not at the top of the local block, syntacitially error, I guess
}
  • A block defines a life scope of the variables in which. – user3422531 Mar 15 '14 at 07:35
  • 3
    "it's just a statement" - actually, it is a **declaration**. A statement would be legal there. The `if` must be followed by a statement, however a brace-enclosed list of declarations and statements counts as a statement. – M.M Mar 15 '14 at 08:31