C中的variables声明放置

我一直认为在C语言中,所有variables都必须在函数的开头声明。 我知道在C99中,规则与C ++中的规则相同,但C89 / ANSI C的variables声明放置规则是什么?

下面的代码用gcc -std=c89gcc -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; } 

cs的声明不应该在C89 / ANSI模式下导致错误?

它编译成功,因为GCC允许它作为GNU扩展,即使它不是C89或ANSI标准的一部分。 如果你想严格遵守这些标准,你必须通过这个标志。

对于C89,您必须在范围块的开头声明所有variables。

所以,你的char c声明是有效的,因为它在for循环范围块的顶部。 但是, char *s声明应该是错误的。

在块顶部对variables声明进行分组可能是由于旧的原始C编译器的限制。 所有现代语言都会推荐,甚至有时甚至会强制声明局部variables:最初初始化的地方。 因为这样可以摆脱使用随机值的风险。 分离声明和初始化也可以防止你使用“const”(或“final”)。

C不幸的是继续接受旧的,顶级的声明方式向后兼容C(一个C兼容性拖出许多其他…)但C + +试图摆脱它:

  • C ++引用的devise甚至不允许块分组的顶部。
  • 如果单独声明和初始化一个C ++本地对象,那么你就付出了额外构造函数的代价。 如果没有参数的构造函数不存在,那么你甚至不能将它们分开!

C99开始向这个相同的方向移动C.

如果你担心找不到局部variables被声明的地方,那么这意味着你有一个更大的问题:封闭块太长,应该被拆分。

https://www.securecoding.cert.org/confluence/display/cplusplus/DCL19-CPP.+Initialize+automatic+local+variables+on+declaration

从可维护性而非句法性的angular度来看,至less有三种思路:

  1. 在函数的开头部分声明所有的variables,这样他们就可以在一个地方,一眼就能看到全面的列表。

  2. 声明所有variables尽可能靠近他们第一次使用的地方,所以你会知道为什么每个都需要。

  3. 在最内层的范围块的开始部分声明所有的variables,这样它们就会尽快超出范围,并允许编译器优化内存,并告诉你是否意外地将它们用在了你没有打算的地方。

我通常更喜欢第一种select,因为我发现其他人经常强迫我通过代码寻找声明。 预先定义所有variables也使得从debugging器初始化并观察它们变得更容易。

我有时会在一个较小的范围块中声明variables,但只是为了一个很好的原因,其中我很less。 一个例子可能是在fork()之后声明只有subprocess需要的variables。 对我来说,这个视觉指标是一个有用的提醒他们的目的。

正如其他人所指出的,即使在“C89”模式下,GCC在这方面也是宽容的(甚至可能还有其他编译器,这取决于它们被调用的参数),除非使用“迂腐”检查。 说实话,没有很多好理由没有迂腐; 高质量的现代代码应该总是在没有警告的情况下进行编译(或者只有极less数情况下,如果你知道自己正在做的事情对于编译器来说是可疑的,那么可能是错误的),所以如果你不能用迂腐的设置编译代码,那么可能需要一些注意力。

C89要求在每个范围内的任何其他语句之前声明variables,稍后的标准允许更接近于使用的声明(这可以更直观和更高效),特别是在for循环中同时声明和初始化循环控制variables。

我将引用gcc版本4.7.0手册中的一些语句作为清楚的解释。

“编译器可以接受几个基本标准,比如'c90'或'c ++ 98',以及那些标准的GNU方言,如'gnu90'或'gnu ++ 98'。通过指定一个基本的标准,编译器将接受遵循该标准的所有程序以及那些使用GNU扩展名的程序,例如,'-std = c90'closures了某些与ISO C90不兼容的GCC特性,例如asm和typeof关键字其他GNU扩展在ISO C90中没有意义,例如省略?:expression式的中间项。

我认为你的问题的关键是为什么即使使用“-std = c89”选项,gcc也不符合C89。 我不知道你的gcc的版本,但我认为不会有太大的区别。 gcc的开发者告诉我们,选项“-std = c89”只是意味着与C89相矛盾的扩展被closures。 所以,它与C89中没有意义的扩展无关。 而不限制variables声明的扩展属于与C89不矛盾的扩展。

说实话,大家都会认为它应该完全符合C89的选项“-std = c89”。 但事实并非如此。 至于声明所有variables开头好坏的问题只是一个习惯问题。