关于C变量声明的新手问题

6tqwzwtp  于 2022-12-11  发布在  其他
关注(0)|答案(3)|浏览(245)

我正在阅读一本关于C的介绍书,我看到了下面的一段话:

但下列程式码会以预期的输出进行编译:

#include <stdio.h>

int main()
{
    for(int i = 0; i<=10; i++)
    {
        int val = i + 1;
        
        int x = val * val;
        
        printf("%d\n", x);

        int y = x;

    }

    return 0;
}

我使用https://www.onlinegdb.com/,在上面的代码中,我在第一个可执行语句之后声明了许多变量。这对我来说与书中的章节所讲述的不匹配。
我是不是误解了这本书的意思?

2ic8powd

2ic8powd1#

在C 1990 6.6.2中,声明只能出现在文件范围(函数定义之外)或复合语句的开头。C 1990 6.6.2中复合语句的语法是:

  • 复合语句 *

    `{` * 声明列表 *opt* 语句列表 *opt `}`

也就是说,复合语句是{,后面跟着零个或多个声明,然后是零个或多个语句,最后是},所以声明必须在前面。
在C 1999 6.8.2中,此更改为:

  • 复合语句 *

    `{` * 块项目列表 * 选项`}`
  • block-item-list* 是 block-item 的列表,其中的每一个都可以是 * 声明 * 或 * 语句 *,因此声明和语句可以自由混合。

在您的示例中,声明int val = i + 1;int x = val * val;没有出现在其复合语句中的可执行语句之后。复合语句以{开头,{紧接在int val = i + 1;之前,因此该声明位于复合语句的开头。
另一个变化是for语法在C 1990 6.6.5中有所改变:
for( * 表达式 * 选择; * 表达式 * 选择; * 表达式 * 选择) * 语句 *
C 1999 6.8.5中的两种形式的选择:
for( * 表达式 * 选择; * 表达式 * 选择; * 表达式 * 选择) * 语句 *
for( * 声明**表达式 * 选择; * 表达式 * 选择) * 语句 *
(Note* 声明 * 包括终止;。)
这就解释了为什么for(int i = 0; i<=10; i++)中可以有int i = 0

cnjp1d6j

cnjp1d6j2#

这本书指的是 * 30多年前 * 的原始C规范,称为“ANSI C”或“C89”或“C90”。如果我们在C89模式下运行C编译器,-std=c89,我们会从您的代码中得到警告...

cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c89 -pedantic -g -fsanitize=address   -c -o test.o test.c
test.c:5:9: warning: variable declaration in for loop is a C99-specific feature [-Wc99-extensions]
    for(int i = 0; i<=10; i++)
        ^
test.c:5:9: warning: GCC does not allow variable declarations in for loop initializers before C99 [-Wgcc-compat]
2 warnings generated.

C99,1999年对C语言的更新,使这一点变得不真实。用-std=c99运行你的代码不会给出任何警告。C99对语言做了这一点和其他有影响的修改,比如//注解。
还有C11和最新的稳定版本的C是C17,但编译器对两者的支持是不稳定的。
为什么这本书指的是这样一个旧版本的语言?C语言自1978年就已经存在,有很多旧代码和旧编译器。C编译器在完全采用新标准方面非常缓慢,这使得作者相当保守。一个很大的绊脚石是Microsoft Visual C++直到2013年才实现C99!因此,ANSI C在很长一段时间内都是最低公分母。
最近几年,C编译器在标准遵从性方面做得更好了,所以您可以依赖C99(它已经成熟到可以喝酒了)作为您的基线。

gj3fmq9x

gj3fmq9x3#

示例中的所有变量在使用之前都已声明。
这些声明包括:

int i ...;
int val ...;
int x ...;

注意所有声明都发生在相应块中的第一个函数调用之前。换句话说:i、瓦尔和x都在printf之前声明。
正如评论中所说:一些旧书可能会参考C的旧版本。例如,for循环中的变量声明是C99附带的。从C99开始,你也可以在块的中间声明变量。所以你可以在printf之后声明一些int y;,你的代码仍然可以编译。

相关问题