mcj*_*erz 121 c declaration c89
我一直认为在C中,所有变量都必须在函数的开头声明.我知道在C99中,规则与C++中的规则相同,但C89/ANSI C的变量声明放置规则是什么?
以下代码使用gcc -std=c89和成功编译gcc -ansi:
#include <stdio.h>
int main() {
int i;
for (i = 0; i < 10; i++) {
char c = (i % 95) + 32;
printf("%i: %c\n", i, c);
char *s;
s = "some string";
puts(s);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不应该在C89/ANSI模式下声明c并s导致错误吗?
mip*_*adi 138
它成功编译,因为GCC允许它作为GNU扩展,即使它不是C89或ANSI标准的一部分.如果您想严格遵守这些标准,您必须通过-pedantic旗帜.
小智 74
对于C89,您必须在范围块的开头声明所有变量.
因此,您的char c声明是有效的,因为它位于for循环范围块的顶部.但是,char *s声明应该是一个错误.
Mar*_*rcH 30
由于旧的原始C编译器的限制,在块的顶部对变量声明进行分组是遗留的.所有现代语言都推荐甚至有时甚至强制在最新点声明局部变量:它们首先被初始化.因为这样可以避免错误地使用随机值的风险.分离声明和初始化也会阻止你尽可能使用"const"(或"final").
不幸的是,C++继续接受旧的顶级声明方式以向后兼容C(一个C兼容性拖出了许多其他人......)但是C++试图摆脱它:
C99开始向同一方向移动C.
如果您担心没有找到声明局部变量的位置,那么这意味着您有一个更大的问题:封闭块太长并且应该拆分.
Ada*_*iss 22
从可维护性而非句法角度来看,至少有三种思路:
在函数的开头声明所有变量,这样它们就会在一个地方,你将能够一目了然地看到综合列表.
声明所有变量尽可能接近它们首次使用的位置,因此您将知道为什么需要每个变量.
在最内部作用域块的开头声明所有变量,因此它们将尽快超出作用域并允许编译器优化内存并告诉您是否意外地将它们用于您不想要的地方.
我通常更喜欢第一个选项,因为我发现其他人经常强迫我通过代码搜索声明.预先定义所有变量也可以更容易地从调试器初始化和观察它们.
我有时会在一个较小的范围块中声明变量,但只是为了一个好的理由,我很少.一个例子可能是在a之后fork(),声明只有子进程所需的变量.对我而言,这个视觉指示器有助于提醒他们的目的.
小智 6
正如其他人所指出的那样,GCC在这方面是允许的(并且可能是其他编译器,取决于他们被称为的参数),即使在'C89'模式下,除非你使用'迂腐'检查.说实话,没有很多很好的理由没有迂腐; 高质量的现代代码应该总是在没有警告的情况下进行编译(或者很少有人知道你正在做一些特定的事情,这对编译器来说可能是一个可能的错误),所以如果你不能用迂腐的设置编译你的代码,那么它可能需要引起注意.
C89要求在每个范围内的任何其他语句之前声明变量,以后标准允许声明更接近使用(可以更直观和更有效),尤其是在'for'循环中同时声明和初始化循环控制变量.