简体   繁体   English

声明/定义为C和C ++中的语句

[英]Declarations/definitions as statements in C and C++

I was confused when this wouldn't compile in C: 当这不能在C中编译时我很困惑:

int main()
{
    for (int i = 0; i < 4; ++i)
        int a = 5; // A dependent statement may not be declaration

    return 0;
}

I'm used to C++ where this will compile. 我已经习惯了将要编译的C ++。 I just stared dumbfounded for a while until I remembered an answer here on SO about how in C and C++ different things are considered "statements". 我只是愣了一会儿,直到我记得这里的答案是关于如何在C和C ++中将不同的东西视为“陈述”。 This was in regard to a switch statement. 这是关于switch语句的。 A "statement" after the for loop brackets must be present both in C and C++. for循环括号后面的“语句”必须同时出现在C和C ++中。 This can be done in both either adding a semicolon or creating a { } squiggly bracket block. 这可以在添加分号或创建{}波浪形支架块的情况下完成。

In C++ "int a = 7;" 在C ++中“int a = 7;” is considered a declaration, definition, and initialisation. 被视为声明,定义和初始化。 In CI believe it is also considered all of these, however in C it is not considered a "statement". CI认为它也被认为是所有这些,但在C中它不被视为“声明”。

Could someone exactly clarify why in C this isn't a statement whereas in C++ it is? 有人可以准确地澄清为什么在C中这不是一个陈述,而在C ++中它是? This is confusing my concept of what a statement is, because one language says it is, and another says it isn't, so I'm kind of confused. 这让我对一个陈述的概念感到困惑,因为一种语言说的是,而另一种语言则说不是,所以我有点困惑。

C++ allowed that the "substatement" of an iteration statement was implicitly a compound statement ([stmt.iter]) C ++允许迭代语句的“子语句”隐含为复合语句([stmt.iter])

If the substatement in an iteration-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original statement. 如果iteration-statement中的子语句是单个语句而不是复合语句,则就好像它被重写为包含原始语句的复合语句一样。 Example: 例:

while (--x >= 0)
   int i;

can be equivalently rewritten as 可以等同地重写为

while (--x >= 0) {
   int i;
}

the C standard does not have this language. C标准没有这种语言。

Additionally, the definition of a statement changed in C++ to include a declaration statement , so even if the above change wasn't made, it would still be legal. 此外, 语句的定义在C ++中更改为包含声明语句 ,因此即使未进行上述更改,它仍然是合法的。


The reason that adding braces makes it work is because your declaration now becomes a compound-statement which can include declarations. 添加大括号使其工作的原因是因为您的声明现在变成了一个可以包含声明的复合语句

You are allowed to have an identifier in a loop body without braces, so you can do this instead: 您可以在没有大括号的循环体中拥有标识符 ,因此您可以这样做:

int a = 5;
for (int i = 0; i < 4; ++i)
    a;

In C++, a statement is (C++17 standard draft) 在C ++中,一个声明是(C ++ 17标准草案)

excerpt from [gram.stmt]

statement:
    labeled-statement
    attribute-specifier-seqopt expression-statement
    attribute-specifier-seqopt compound-statement
    attribute-specifier-seqopt selection-statement
    attribute-specifier-seqopt iteration-statement
    attribute-specifier-seqopt jump-statement
    declaration-statement
    attribute-specifier-seqopt try-block

init-statement:
    expression-statement
    simple-declaration

declaration-statement:
    block-declaration

...

Note that there are declaration statements in C++, which are declarations, and are statements. 请注意,C ++中有声明语句,它们是声明,而且是语句。 Similarly, simple declarations are init statements. 类似地,简单声明是init语句。 Not all declarations are statements though. 但并非所有声明都是陈述。 The grammar of declarations contains things that are not in the list of statements: 声明语法包含不在语句列表中的内容:

excerpt from [gram.dcl]

declaration:
    block-declaration
    nodeclspec-function-declaration
    function-definition
    template-declaration
    deduction-guide
    explicit-instantiation
    explicit-specialization
    linkage-specification
    namespace-definition
    empty-declaration
    attribute-declaration

block-declaration:
    simple-declaration
    asm-definition
    namespace-alias-definition
    using-declaration
    using-directive
    static_assert-declaration
    alias-declaration
    opaque-enum-declaration

simple-declaration:
    decl-specifier-seq init-declarator-listopt ;
    attribute-specifier-seq decl-specifier-seq init-declarator-list ;
    attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ identifier-list ] initializer ;

...

The list of declaration grammars continues on for a few pages. 声明语法列表将持续几页。


In C, a statement is (C11 standard draft) 在C中,声明是(C11标准草案)

excerpt from Statements and blocks

statement:
    labeled-statement
    compound-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement

Note that there are no declarations that are statements in C. 请注意,没有声明是C中的语句。


So, the meaning of statement is clearly different in the languages. 因此, 语句的含义在语言上明显不同。 Statement in C++ appears to have a broader meaning than statement in C. C ++中的语句似乎比C中的语句具有更广泛的含义。

According to cppreference, C++ includes following types of statements : 根据cppreference, C ++包含以下类型的statements

  1. expression statements; 表达陈述;
  2. compound statements; 复合语句;
  3. selection statements; 选择陈述;
  4. iteration statements; 迭代语句;
  5. jump statements; 跳转声明;
  6. declaration statements; 声明;
  7. try blocks; 尝试块;
  8. atomic and synchronized blocks 原子和同步块

While C considers following types of statements : C考虑以下类型的statements

  1. compound statements 复合语句
  2. expression statements 表达陈述
  3. selection statements 选择陈述
  4. iteration statements 迭代语句
  5. jump statements 跳转声明

As you can notice, declarations are not considered statements in C, while it is not this case in C++. 正如您所注意到的,声明在C中不被视为statements ,而在C ++中则不是这种情况。

For C++: 对于C ++:

int main()
{                                     // start of a compound statement
    int n = 1;                        // declaration statement
    n = n + 1;                        // expression statement
    std::cout << "n = " << n << '\n'; // expression statement
    return 0;                         // return statement
}                                     // end of compound statement

For C: 对于C:

int main(void)
{                          // start of a compound statement
    int n = 1;             // declaration (not a statement)
    n = n+1;               // expression statement
    printf("n = %d\n", n); // expression statement
    return 0;              // return statement
}                          // end of compound statement

In C++ declarations are statements while in C declarations are not statements. 在C ++声明中,语句在C声明中不是语句。 So according to the C grammar in this for loop 所以根据这个for循环中的C语法

for (int i = 0; i < 4; ++i)
    int a = 5;

int a = 5; int a = 5; must be a substatement of the loop. 必须是循环的子语句。 However it is a declaration. 不过这是一个宣言。

You could make the code to be compiled in C by using the compound statement as for example 例如,您可以使用复合语句使代码在C中编译

for (int i = 0; i < 4; ++i)
{
    int a = 5;
}

though the compiler can issue a diagnostic message saying that the variable a is not used. 虽然编译器可以发出一条诊断消息,说明没有使用变量a

One more consequence that in C declarations are not statements. C语句中的另一个后果是语句不是。 You may not place a label before a declaration in C. For example this program 您不得在C语句中放置标签。例如,此程序

#include <stdio.h>

int main(void) 
{
    int n = 2;

    L1:
    int x = n;

    printf( "x == %d\n", x );

    if ( --n ) goto L1; 

    return 0;
}

does not compile in C though it compiles as a C++ program. 虽然它编译为C ++程序,但不会在C中编译。 However if to place a null-statement after the label then the program does compile. 但是,如果在标签后面放置一个null语句,那么程序就会编译。

#include <stdio.h>

int main(void) 
{
    int n = 2;

    L1:;
    int x = n;

    printf( "x == %d\n", x );

    if ( --n ) goto L1; 

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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