我听说(可能是从一位老师那里)应该在程序/函数之上声明所有变量,并且在语句中声明新变量可能会导致问题.

但后来我在读《K&R和我遇到了这样一句话:"变量声明(包括初始化)可以跟在引入任何复合语句的左大括号后面,而不仅仅是函数开头的语句.".他举了一个例子:

if (n > 0){
    int i;
    for (i=0;i<n;i++)
    ...
}

我对这个概念做了一些try ,它甚至适用于array.例如:

int main(){
    int x = 0 ;

    while (x<10){
        if (x>5){
            int y[x];
            y[0] = 10;
            printf("%d %d\n",y[0],y[4]);
        }
        x++;
    }
}

那么什么时候我不能声明变量呢?例如,如果我的变量声明不在大括号后面怎么办?比如这里:

int main(){
    int x = 10;

    x++;
    printf("%d\n",x);

    int z = 6;
    printf("%d\n",z);
}

根据程序/机器的不同,这会导致故障吗?

推荐答案

我也经常听说把变量放在函数的顶端是最好的方法,但我强烈反对.我更喜欢将变量限制在尽可能小的范围内,这样它们就不会被误用,也就不会有太多的东西填满我的思维空间.

虽然所有版本的C都允许词法块作用域,但声明变量的位置取决于目标C标准的版本:

C99及更高版本或C++

像GCC和clang这样的现代C编译器支持C99C11标准,这允许您在语句可以到达的任何位置声明变量.变量的作用域从声明的点开始到挡路的末尾(下一个右大括号).

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line
   int z = 42;
   printf("%d", z);   // z is in scope in this line
}

还可以在循环初始值设定项中声明变量.变量将只存在于循环内部.

for(int i=0; i<10; i++){
    printf("%d", i);
}

ANSI C(C90)

如果你的目标是旧的ANSI C标准,那么你只能在一个大括号1后立即声明变量.

不过,这并不意味着您必须在函数的顶部声明所有变量.在C语言中,您可以将括号分隔的挡路放在语句可以放到的任何位置(而不仅仅是在if后或for后),并且可以用它来引入新的变量范围.以下是前面C99示例的ANSI C版本:

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line

   {
       int z = 42;
       printf("%d", z);   // z is in scope in this line
   }
}

{int i; for(i=0; i<10; i++){
    printf("%d", i);
}}

1请注意,如果使用gcc,则需要传递--pedantic标志,以使其实际执行C90标准,并抱怨变量声明在错误的位置.如果只使用-std=c90,它会使gcc接受C90的超集,这也允许更灵活的C99变量声明.

C++相关问答推荐

初始化char数组-用于初始化数组的字符串是否除了存储数组的位置之外单独存储在内存中

我可以动态分配具有空类型函数的矩阵吗?

如何将FileFilter添加到FileDialog GTK 4

球体—立方体重叠:无、部分或全部?

为什么下面的C代码会进入无限循环?

C中出现分段错误后关闭文件

返回一个包含数组的 struct

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

以下声明和定义之间的区别

当输入负数时,排序算法存在问题

SSH会话出现意外状态

防止C++中递归函数使用堆栈内存

为什么数组的最后一个元素丢失了?

覆盖读取函数,但当文件描述符为3或4时,我有问题

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

使用ld将目标文件链接到C标准库

如何在不读取整个字符串的情况下删除UTF8字符串的尾随空格以提高性能?

浮点正零何时不全为零?

将指针的地址加载到寄存器内联拇指组件中

如何在 C 中编辑 struct 体中的多个变量