关于作用域,变量最优的声明方式是什么?

8
我主要是关于C编程的问题,但任何语言的见解都欢迎。
在C语言中,变量声明只允许出现在代码块的开头。我一直认为应该在函数的开头声明即将使用的所有变量。但有很多情况下,我会有一个仅在循环(或类似的块)中使用的变量。
例如,一个用于存储返回值的临时变量:
while ( whatever ) {
  int ret;
  ret = getSomeValue();
}

或者需要保留某些状态的情况下:

while ( whatever ) {
  static int count=0;
  count++;
}

我想知道在控制流块(如if-else、for循环、while循环等)内声明变量是否被认为是不妥当的,或者是否存在任何负面影响。
变量是否应该始终具有最紧密的范围?静态声明如何处理?
编辑: 好吧,我可能应该说一下,我知道C99在声明变量的位置上更加自由,但是从我看到的大量C代码来看,它们通常仍在顶部声明。此外,我使用的是VS2K8,它仍然会抱怨声明问题。
此外,考虑到我已经有了两个关闭此主题的投票,我要明确表示我更关心性能和编译器方面,而不是任何风格上的问题。

在 C99 之前,它们需要在块的开头... 超过 11 年了。我认为这已经足够说明 "在 C 中,你不需要在开头声明它"。另外,通常情况下,答案是哪个更简单、更易读就用哪个。 - GManNickG
我知道在gcc的旧版本中,当你试图在循环内部声明时,它会经常抱怨,你必须在循环外部声明。 - Jim
3
提到C语言,我知道它只允许变量声明在代码块的开头。以我最像Leonard H McCoy的声音说:天啊,伙计,你到哪里去了? - paxdiablo
3个回答

7

一个经验法则是变量应尽可能作为局部变量。如果可以将其设为const,那就更好了。


5

好的,关于块顶部的声明是C89和K&R的事情,但自从C99以来,您可以混合声明和语句。这种风格可能会持续下去,可能有很好的理由,但并不是必需的。

曾经有一段时间,如果您在使用的地方声明了很多局部变量,某些编译器会做得更好,因为它可以使寄存器分配更好。在C99之前,您必须在块的顶部声明它们或使用供应商扩展,但您仍然可以决定只在代码的本地区域中实际使用每个变量。

可能在某个时候直接支持更灵活的声明放置方式似乎很重要,但我怀疑这些天优化器不需要那种帮助。

一些编码标准要求在函数的顶部声明。我不知道这是否是为了找到它们,还是仅仅留下了不这样做可能会限制向后移植性的日子。

一般来说,标准越正式,就越不喜欢交错语句和声明,除了循环控制变量。就个人而言,我不认为这有问题。

混合声明的优点:局部性。对于编译器和读者都有好处。在函数顶部声明循环变量可能会带来什么好处?在页面下方为不相关的目的重复使用变量似乎会导致混淆,并且在可能出现意外交互的情况下是不明智的。

分组声明的优点:代码以主观方式看起来更清洁,您知道去哪里找到每个声明,如果您的函数顶部离变量的使用太远,也许这告诉您需要从明显过大的函数中提取第二个或第三个函数。


作用域和混合是不同的事情。OP处理前者,而您处理后者。您能否请详细说明一下作用域声明? - Basilevs
虽然这些事实可能存在,但我不了解很多可以用来回答你的客观要素。我可以说我相信减少副作用。正如 Roger Zelazny 的 Amber 小说一样,我在写 C 代码时试图找到函数式编程的淡影,所以声明变量并在使用它们的地方右侧是我的风格。 - DigitalRoss

2
变量的声明位置不会影响代码生成。所有函数变量都会在第一行代码执行之前放置在堆栈上(至少观察到了这种行为)。正如您已经知道的那样,关于变量声明的规则早已死亡。在顶部声明变量具有以下优点:
  • 当所有变量都可以在同一位置找到时,更容易阅读
  • 如果需要突然访问一个变量而它还没有被声明,你不需要担心重新排列代码(除非你有意想要防止这种情况发生)。
是的,我会尽可能地将变量设置为本地变量。如果一个变量只在循环或控制流中使用,甚至只在无意义的{}对中使用(我曾经用来防止名称冲突),那么就在那里声明它们。以for循环中的著名n或i变量为例。如果你有多个,你将需要为每个for循环提供一个唯一的变量名,这会变得很麻烦。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接