0

我最近在办公室参加的一次编码风格演讲提倡在定义变量时不应将其分配(到默认值)。相反,它们应该在使用前被分配一个默认值。所以,像

int a = 0;

应该不赞成。

显然,'int' 的示例很简单,但对于其他类型(如指针等)也是如此。

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

上面的方法对我来说只对结构有用,即你只在使用之前对它们进行memset。如果仅在错误分支中使用(或填充)结构,这将是有效的。

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

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

4

5 回答 5

1

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

就编码风格而言,我认为您过于从字面上理解了。例如,您的陈述在以下情况下是正确的......

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 结构初始化器)中一样:

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

        write_foo(&foo);
}
于 2009-06-11T06:25:07.763 回答
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 是没有意义的,因为它会停止编译器警告您已覆盖每个分支。

于 2009-06-19T14:07:26.770 回答
0

我有点同意这个建议,尽管我不完全确定标准对此有什么规定,而且我非常怀疑关于编译器警告的说法是否属实。

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

在 1990 年代,这个建议是错误的。如今,它是正确的。

于 2009-06-11T05:34:55.397 回答
0

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

于 2009-06-11T05:35:23.197 回答
0

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

由于我在 RTOS 和高性能但低资源系统上工作,因此我们使用的编译器可能无法捕获未初始化的使用。尽管我怀疑现代编译器也可以 100% 依赖。

在广泛使用宏的大型项目中,我见过很少的情况,甚至 Kloclwork /Purify 都未能找到未初始化的用法。

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

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

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

于 2009-06-11T06:58:06.057 回答