C89和变量初始化

时间:2015-09-25 16:28:20

标签: c c89 ansi-c

C89(C90,ANSI-C)不允许使用代码混合变量声明。我想知道变量初始化在多大程度上被考虑"代码"。

也许它只对使用常量表达式初始化有效?

具体来说,如果我正在编写C代码并且我想要安全地玩(最大限度地兼容ANSI-C编译器),是否应该认为以下是安全的?

  void f1(void) { 
      int x = 30;
      int y = 40;
      int z;
      /* ... */
  }

  void f2(void) { 
      int x = 30, y = 40;
      int z;
      /* ... */
  }

  #define MYCONST (90)
  void f3(void) { 
      int x = 3; 
      int y = 4 + MYCONST;
      int z;
      /* ... */
  }

  void f4(void) { 
      int x = 3;
      int y = time(NULL);
      int z = 10 + x;
      /* ... */
  }

6 个答案:

答案 0 :(得分:3)

在C89 / C90中,在非变量声明的代码之后声明变量是不合法的。

void foo()
{
   int i = 0;
   i = 2;      // Does not declare a variable.
   int j = 10; // Not legal.
}

上面的代码适用于gcc。但是,如果您使用-pedantic标志,您将看到一条类似于以下内容的警告消息:

soc.c:5:4: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
    int j = 10;

但是,您可以拥有任意数量的变量声明。初始化变量的代码可以使用语言提供的任何方法。你所有的例子都很好。

答案 1 :(得分:1)

您的所有示例都是合法的,可以安全地与符合ANSI-C的编译器一起使用。

使用gcc-std=c89-pedantic中编译代码不会产生任何警告。

答案 2 :(得分:1)

C89不允许在同一范围内混合声明和语句。我们在这里指的是函数内部的声明和语句,因为C语句中的函数不允许使用语句。

int a = foo(a, b);  /* declared at block-scope */

上面的行是(有效的C89)声明,而不是声明所以你的所有函数f1,f2,f3和f4都是有效的C89。

但是,您可以在不同的范围内混合声明和语句:

void bar(void)
{
    int i = 0;  /* declaration */
    i++;  /* statement */
    {
        int j = 0;  /* declaration */
        j++;  /* statement */
     }
 }

上述功能有效C89。

答案 3 :(得分:1)

C99标准的前言本身提及"混合声明和代码"作为C90的变化之一。这是恕我直言,这是一个糟糕的选择,因为它根本不清楚什么"代码"手段。它可以轻松引用可以出现在C源文件中的所有内容。

C99所做的实际更改是允许在一个块中混合声明和语句声明语句之间的区别由语言语法明确定义。

您的一个示例中的行:

int y = time(NULL);

是声明,而不是声明,即使它导致在运行时执行某些代码。是否存在初始化程序,以及该初始化程序是否为常量表达式,不会影响某些内容是否被视为声明。

您的问题中的所有四个示例在C89 / C90,C99和C11中都有效。在每种情况下,块只包含声明,没有语句。

如果要在C90中混合声明和语句,可以通过引入嵌套块来实现:

void func(void) {
    int x = 1; /* a declaration */
    x = 2;     /* a statement; no declarations may follow in C90 */
    {
        int y = 3; /* a declaration */
        y = 4;     /* a statement */
    }
}

内部阻止它本身就是一个声明。因为它是一个声明,它可以出现在该上下文中。因为它是一个复合语句,它本身可以包含一系列声明,后跟一系列语句。

即使在C99或C11中,引入这样的嵌套块也是有利的。 y的范围和生命周期在包含其声明的块的结束}处结束。限制声明的范围可以使代码更容易理解。

(有点背景:C89是ANSI在1989年发布的标准.ISO采用了它,文档中有一些变化,但没有用它描述的语言,如C90.ISO发布了更新标准,C99,然后由ISO.ISO采用另一个更新的标准C11,它也被ANSI采用。根据ANSI和ISO,2011标准是当前版本,所有早期版本都已过时。但由于历史原因,短语& #34; ANSI C"通常是指1989年和1990年版所描述的语言。我通常试图避免使用短语" ANSI C"而是指#34; ISO C" ,如果它是相关的,加上出版年份。)

答案 4 :(得分:0)

使用以下代码对C89 / 99版本差异的补充观察:
(C标准的C99扩展似乎在可以放置其他声明的地方变得不那么迂腐)

int main() 
{ 
    int a; //declaration only
    int b; //declaration only
    b = 5; //assignment only (no declaration)
    int c; //declaration only  (fails C89, Compiles C99)

    return 0; 
}

下图说明了使用C89设置时的错误,以及在赋值语句后尝试声明时的错误。 (当设置为使用C99时,代码编译时没有错误)

enter image description here

答案 5 :(得分:-2)

F1,f2,f3有效但f4不是因为声明和定义是混合的