C89 和变量初始化
C89 and variable initialization
C89(C90、ANSI-C)不允许在代码中混用变量声明。我想知道变量初始化在多大程度上被认为是 "code".
也许只有用常量表达式初始化才有效?
具体来说,如果我正在编写 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;
/* ... */
}
should the following be considered safe?
您发布的所有代码都是安全的。
- 您可以在任何范围内声明任意数量的变量。
- 初始化变量的代码可以使用语言提供的任何方法。
但是,在非变量声明代码之后声明变量是不合法的。
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;
F1、f2、f3 有效,但 f4 无效,因为声明和定义是混合的
您的所有示例都是合法的,可以安全地与符合标准的 ANSI-C 编译器一起使用。
使用 -std=c89
和 -pedantic
编译 gcc
中的代码不会生成任何警告。
关于 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 设置并在 assignment 语句后尝试 declaration 时出现的错误。 (设置为使用C99时,代码编译无错误)
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有效
C99 标准的前言本身提到 "mixed declarations and code" 作为对 C90 的更改之一。恕我直言,这是一个糟糕的用词选择,因为根本不清楚 "code" 是什么意思。它可以轻松引用 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标准是当前标准,之前的所有版本都已经过时了。但是由于历史原因,短语 "ANSI C" 通常指的是 1989 和 1990 版本描述的语言。我通常尽量避免使用短语 "ANSI C",而是指 "ISO C",如果相关的话加上出版年份。)
C89(C90、ANSI-C)不允许在代码中混用变量声明。我想知道变量初始化在多大程度上被认为是 "code".
也许只有用常量表达式初始化才有效?
具体来说,如果我正在编写 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;
/* ... */
}
should the following be considered safe?
您发布的所有代码都是安全的。
- 您可以在任何范围内声明任意数量的变量。
- 初始化变量的代码可以使用语言提供的任何方法。
但是,在非变量声明代码之后声明变量是不合法的。
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;
F1、f2、f3 有效,但 f4 无效,因为声明和定义是混合的
您的所有示例都是合法的,可以安全地与符合标准的 ANSI-C 编译器一起使用。
使用 -std=c89
和 -pedantic
编译 gcc
中的代码不会生成任何警告。
关于 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 设置并在 assignment 语句后尝试 declaration 时出现的错误。 (设置为使用C99时,代码编译无错误)
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有效
C99 标准的前言本身提到 "mixed declarations and code" 作为对 C90 的更改之一。恕我直言,这是一个糟糕的用词选择,因为根本不清楚 "code" 是什么意思。它可以轻松引用 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标准是当前标准,之前的所有版本都已经过时了。但是由于历史原因,短语 "ANSI C" 通常指的是 1989 和 1990 版本描述的语言。我通常尽量避免使用短语 "ANSI C",而是指 "ISO C",如果相关的话加上出版年份。)