简体   繁体   中英

"if" statement syntax differences between C and C++

if (1) int a = 2;

This line of code is valid C++ code (it compiles at the very least) yet invalid C code (doesn't compile). I know there are differences between the languages but this one was unexpected.

I always thought the grammar was

if (expr) statement

but this would make it valid in both.

My questions are:

  1. why doesn't this compile in C?
  2. why does this difference exist?

This is a subtle and important difference between C and C++. In C++ any statement may be a declaration-statement . In C, there is no such thing as a declaration-statement , and instead a declaration can appear instead of a statement within any compound-statement .

From the C grammar (C17 spec):

compound-statement : "{" block-item-list opt "}"
block-item-list : block-item | block-item-list block-item
block-item : declaration | statement

From the C++ grammar (C++14 spec):

compound-statement : "{" statement-seq opt "}"
statement-seq : statement | statement-seq statement
statement : ... | declaration-statement | ...

It is not clear why this difference exists, it is just the way the languages evolved. The C++ syntax dates all the way back to (at least) C++85. The C syntax was introduced some time between C89 and C99 (in C89, declarations had to be at the beginning of a block)


In the original 85 and 89 versions of C++, the scope of a variable defined in a declaration-statement was "until the end of the enclosing block "). So a declaration in an if like this would not immediately go out of scope (as it does in more recent versions) and instead would be in scope for statements following the block in the same scope. This could lead to problems with accessing uninitialized data when the condition was false. Worse, if the var had a non-trivial destructor, that would be called when the scope ended, even if it had never been initialized! I suspect trying to avoid these kinds of problems is what lead to C adopting a different syntax.

Chris's answer (and others) shows how the grammar is different.

I want to point out that if (1) int a = 2; doesn't make sense in C but it does in C++. Since we don't have a block but just 1 statement/declaration there is no possible further use of the variable declared (it goes out of scope immediately). In C this would make no sense to allow, but in C++ constructors and destructors can have side effects, so defining and initializing a variable that goes out of scope immediately can be useful and must be allowed.

It's because C and C++ define statement differently.

In C, declarations are not classified as statements. AC compound statement consists of an opening { , an option list of block-item s, and a closing } , where a block-item either a declaration or a statement . (This was changed in C99, when C added the ability to mix declarations and statements within a block.)

In C++, a declaration is classified as a statement (but only if it's inside a compound statement). This allows a simpler definition of a compound-statement : it's a { , followed by an optional list of statement s, followed by a } .

The difference doesn't have much practical effect; it's always possible to work around it. One effect is that it's legal in C++ for a declaration immediately follow a case label, but in C it's not legal.

In C, a declaration and a statement are distinct entities.

In C++, aa subset of declarations called a block-declaration is a type of statement, specifically it is a declaration-statement . These include simple declarations like int a=2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM