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

时间:2018-04-16 16:21:22

标签: c++ c if-statement language-lawyer

当我不能在C:

中编译时,我很困惑
int main()
{
    for (int i = 0; i < 4; ++i)
        int a = 5; // A dependent statement may not be declaration

    return 0;
}

我习惯使用C ++编译。我只是愣了一会儿,直到我记得这里的答案是关于如何在C和C ++中考虑不同的事情&#34;陈述&#34;。这是关于switch语句的。 A&#34;陈述&#34;在for循环括号之后必须同时存在于C和C ++中。这可以在添加分号或创建{}波浪形支架块的情况下完成。

在C ++&#34; int a = 7;&#34;被视为声明,定义和初始化。在C中我相信它也被认为是所有这些,但是在C中它不被视为&#34;陈述&#34;。

有人可以准确地澄清为什么在C中这不是一个声明而在C ++中它是什么?这让我对一个陈述的概念感到困惑,因为一种语言说它是,而另一种语言说它不是,所以我有点困惑。

4 个答案:

答案 0 :(得分:16)

C ++允许&#34;子语句&#34;迭代语句的含义是一个复合语句([stmt.iter])

  

如果iteration-statement中的子语句是单个语句而不是复合语句,那就好像   它被重写为包含原始语句的复合语句。例如:

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

可以等效地重写为

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

C标准没有这种语言。

此外,语句的定义在C ++中已更改为包含声明语句,因此即使上述更改尚未生成,它仍将是合法的。

添加大括号使其工作的原因是因为您的声明现在变为复合语句,其中可以包含声明。

您可以在没有大括号的循环体中拥有标识符,因此您可以这样做:

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

答案 1 :(得分:11)

在C ++中,语句是(C ++ 17标准草案)

get_updates()

请注意,C ++中有声明语句,它们是声明,而且是语句。类似地,简单声明是init语句。但并非所有声明都是陈述。声明语法包含不在语句列表中的内容:

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

...

声明语法列表会持续几页。

在C中,陈述是(C11标准草案)

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 ;

...

请注意,C语句中没有声明声明。

因此,语句的含义在语言上明显不同。 C ++中的语句似乎比C中的语句具有更广泛的含义。

答案 2 :(得分:7)

根据cppreference,C++包含以下类型的statements

  1. 表达式声明;
  2. 复合语句;
  3. 选择陈述;
  4. 迭代声明;
  5. 跳转声明;
  6. 声明声明;
  7. 尝试阻止;
  8. 原子和同步块
  9. 虽然C会考虑以下类型的statements

    1. 复合语句
    2. 表达陈述
    3. 选择陈述
    4. 迭代陈述
    5. 跳转声明
    6. 正如您所注意到的,声明在C中不被视为statements,而在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
      

      对于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, end of function body
      

答案 3 :(得分:2)

在C ++声明中,语句是在C声明中不是语句。所以根据这个for循环中的C语法

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

int a = 5;必须是循环的子语句。不过这是一个宣言。

您可以使用复合语句(例如

)使代码在C中编译
for (int i = 0; i < 4; ++i)
{
    int a = 5;
}

虽然编译器可以发出一条诊断消息,说明没有使用变量a

C声明中的另一个结果不是声明。您不得在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;
}

虽然编译为C ++程序,但不会在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;
}