当前位置:  开发笔记 > Android > 正文

C中的变量声明放置

如何解决《C中的变量声明放置》经验,为你挑选了5个好方法。

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

以下代码使用gcc -std=c89和成功编译gcc -ansi:

#include 
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;
}

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



1> mipadi..:

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


值得注意的是,只有`s`的声明是一个扩展(从C89的角度来看).在C89中声明`c`是完全合法的,不需要扩展.
@AndreyT:是的,在C中,变量声明应该是__block_的开头而不是函数本身; 但是人们会将块与函数混淆,因为它是块的主要例子.
哇.谢谢!我不知道.

2> 小智..:

对于C89,您必须在范围块的开头声明所有变量.

因此,您的char c声明是有效的,因为它位于for循环范围块的顶部.但是,char *s声明应该是一个错误.


@Artelius不太正确.仅当curlies是块的一部分时(不是它们是结构或联合声明或支撑初始化器的一部分.)
非常正确.您可以在任何{...}的开头声明变量.

3> MarcH..:

由于旧的原始C编译器的限制,在块的顶部对变量声明进行分组是遗留的.所有现代语言都推荐甚至有时甚至强制在最新点声明局部变量:它们首先被初始化.因为这样可以避免错误地使用随机值的风险.分离声明和初始化也会阻止你尽可能使用"const"(或"final").

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

C++引用的设计甚至不允许这种顶级块分组.

如果您将C++本地对象的声明和初始化分开,那么您无需支付额外构造函数的成本.如果no-arg构造函数不存在,那么你甚至不能再将它们分开!

C99开始向同一方向移动C.

如果您担心没有找到声明局部变量的位置,那么这意味着您有一个更大的问题:封闭块太长并且应该拆分.

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



4> Adam Liss..:

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

    在函数的开头声明所有变量,这样它们就会在一个地方,你将能够一目了然地看到综合列表.

    声明所有变量尽可能接近它们首次使用的位置,因此您将知道为什么需要每个变量.

    在最内部作用域块的开头声明所有变量,因此它们将尽快超出作用域并允许编译器优化内存并告诉您是否意外地将它们用于您不想要的地方.

我通常更喜欢第一个选项,因为我发现其他人经常强迫我通过代码搜索声明.预先定义所有变量也可以更容易地从调试器初始化和观察它们.

我有时会在一个较小的范围块中声明变量,但只是为了一个好的理由,我很少.一个例子可能是在a之后fork(),声明只有子进程所需的变量.对我而言,这个视觉指示器有助于提醒他们的目的.


我使用选项2或3,因此更容易找到变量 - 因为函数不应该太大,以至于您无法看到变量声明.
如果您使用了一个不错的IDE,则不需要进行代码搜索,因为应该有一个IDE命令来为您找到声明.(Eclipse中的F3)
除非您使用70年代的编译器,否则选项3不是问题.
@Plumenator:选项1不能确保初始化; 我选择在声明时初始化它们,要么是它们的"正确"值,要么是为了保证后续代码在未正确设置时会中断.我说"选择"是因为我写这篇文章后我的偏好已经改为#2,也许是因为我现在使用的是Java而不是C,因为我有更好的开发工具.
我不明白你如何确保选项1中的初始化,有时你只能通过调用另一个函数或执行caclulation来获取块中的初始值.

5> 小智..:

正如其他人所指出的那样,GCC在这方面是允许的(并且可能是其他编译器,取决于他们被称为的参数),即使在'C89'模式下,除非你使用'迂腐'检查.说实话,没有很多很好的理由没有迂腐; 高质量的现代代码应该总是在没有警告的情况下进行编译(或者很少有人知道你正在做一些特定的事情,这对编译器来说可能是一个可能的错误),所以如果你不能用迂腐的设置编译你的代码,那么它可能需要引起注意.

C89要求在每个范围内的任何其他语句之前声明变量,以后标准允许声明更接近使用(可以更直观和更有效),尤其是在'for'循环中同时声明和初始化循环控制变量.

推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有