变量同时定义和分配

时间:2009-06-11 05:24:48

标签: c coding-style initialization c99

我最近在办公室参加的编码风格演示文稿主张在定义变量时不应将变量分配(默认值)。相反,应在使用之前为它们分配默认值。 所以,像

int a = 0;

应该不赞成。

显然,'int'的一个例子是简单的,但对于其他类型也是如此,如指针等。

此外,还提到C99兼容编译器现在在上述情况下发出警告。

上述方法对我来说只对结构有用,即只在使用前才对它们进行记忆。如果仅在错误段中使用(或填充)结构,则这将是有效的。

对于所有其他情况,我发现定义并为默认值分配一个谨慎的练习,因为在编写和维护代码时,由于未初始化的指针,我遇到了很多错误。此外,我相信通过构造函数的C ++也提倡相同的方法,即定义和赋值。

我想知道为什么(如果)C99标准不喜欢定义&分配。他们在做编码风格演示所倡导的内容方面有什么相当的优点吗?

5 个答案:

答案 0 :(得分:1)

在C99中有 no 这样的要求(甚至我知道的指南),编译器也没有警告你。这只是一种风格问题。

就编码风格而言,我认为你太过于字面意思了。例如,您的陈述在以下情况中是正确的......

int i = 0;

for (; i < n; i++)
        do_something(i);

......甚至是......

int i = 1;

[some code follows here]

while (i < a)
        do_something(i);

...但是在我看来,还有其他一些案例可以通过早期的“声明和分配”得到更好的处理。考虑在堆栈上构造的结构或各种OOP结构,如:

struct foo {
        int bar;

        void *private;
};

int my_callback(struct foo *foo)
{
        struct my_struct *my_struct = foo->private;

        [do something with my_struct]

        return 0;
}

或者喜欢(C99 struct initializers):

void do_something(int a, int b, int c)
{
        struct foo foo = {
                .a        = a,
                .b        = b + 1,
                .c        = c / 2,
        };

        write_foo(&foo);
}

答案 1 :(得分:1)

通常我建议在定义变量时初始化变量,如果知道它们应该具有的值,并且如果值不是,则保留变量未初始化。无论哪种方式,使它们尽可能接近其使用范围规则允许。

  

相反,应该在使用之前为它们分配默认值。

通常你根本不应该使用默认值。在C99中,您可以混合代码和声明,因此在为其赋值之前没有必要定义变量。如果您知道它应该采用的值,那么没有必要使用默认值。

  

此外,还提到C99兼容编译器现在在上述情况下发出警告。

不适用于您展示的情况 - 您没有收到int x = 0;的警告。我强烈怀疑有人混淆了这一点。编译器会警告您是否使用变量而不为其赋值,并且如果您有:

... some code ...

int x;

if ( a )
    x = 1;
else if ( b )
    x = 2;
// oops, forgot the last case else x = 3;

return x * y;

然后你会得到一个警告,即x可以在没有初始化的情况下使用,至少使用gcc。

如果您在x之前为if分配值,则不会收到警告,但无论分配是作为初始化还是作为单独的语句完成,都无关紧要。

除非你有特别的理由为两个分支分配两次值,否则没有必要先将默认值分配给x,因为它会停止编译器警告你已覆盖每个分支。

答案 2 :(得分:0)

我有点赞同这个建议,尽管我并不完全确定该标准对此有何说法,但我非常怀疑编译器警告是否属实。

问题是,现代编译器可以并且确实检测到未初始化变量的使用。如果在初始化时将变量设置为默认值,则会丢失该检测。默认值也可能导致错误;当然,就你的例子int a = 0;而言。谁说0a的适当值?

在20世纪90年代,建议会出错。如今,这是正确的。

答案 3 :(得分:0)

我发现将一些默认数据预先分配给变量非常有用,这样我就不必在代码中进行(尽可能多的)空检查。

答案 4 :(得分:0)

由于未初始化的指针,我已经看到了很多错误,我一直主张用NULL_PTR声明每个变量,每个基元都有一些无效/默认值。

由于我从事RTOS和高性能但资源较少的系统,我们使用的编译器可能无法捕获未初始化的用法。虽然我怀疑现代编译器也可以100%依赖。

在广泛使用Macro的大型项目中,我看到了罕见的场景,即使Kloclwork / Purify也未能找到未初始化的用法。

所以我说只要你使用普通的旧C / C ++就坚持下去。

像.Net这样的现代语言可以保证初始化变量,或者为未初始化的变量使用提供编译器错误。以下链接进行性能分析并验证.NET的性能是否达到10-20%。分析非常详细,并得到了很好的解释。

http://www.codeproject.com/KB/dotnet/DontInitializeVariables.aspx