C89和变量初始化

arknldoa  于 2022-12-22  发布在  其他
关注(0)|答案(5)|浏览(186)

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;
      /* ... */
  }
bvjxkvbb

bvjxkvbb1#

下列情况是否应视为安全?
您发布的所有代码都是安全的。
1.您可以在任何范围内拥有任意数量的变量声明。
1.初始化变量的代码可以使用语言提供的任何方法。
但是,在不是变量声明的代码之后声明变量是不法律的的。

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;
2nc8po8w

2nc8po8w2#

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中有效。

jgovgodb

jgovgodb3#

C99标准的前言本身提到“混合声明和代码”是C90的一个变化。恕我直言,这是一个糟糕的措辞,因为根本不清楚“代码”的意思。它可以很容易地指C源文件中出现的任何东西。
C99所做的实际改变是允许在一个块中混合声明和 * statement *。declarationstatement 之间的区别由语言语法明确定义。
下面是您的示例中的一行:

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标准是当前的标准,而且所有早期版本都已过时。但由于历史原因,短语“ANSI C”通常指的是1989年和1990年版本描述的语言。我通常尽量避免短语“ANSI C”,而是指“ISO C”,如果相关的话,再加上出版年份。)

py49o6xq

py49o6xq4#

您的所有示例都是法律的的,可以安全地用于符合ANSI-C的编译器。
使用-std=c89-pedanticgcc中编译代码不会生成警告。

hjzp0vay

hjzp0vay5#

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

相关问题