开源项目中的C99混合声明和代码?
Posted
技术标签:
【中文标题】开源项目中的C99混合声明和代码?【英文标题】:C99 mixed declarations and code in open source projects? 【发布时间】:2011-03-02 21:07:17 【问题描述】:为什么C99 mixed declarations and code 仍然没有用于像Linux kernel 或GNOME 这样的开源C 项目?
我真的很喜欢混合声明和代码,因为它通过将变量的范围限制在尽可能窄的范围内,使代码更具可读性并防止难以看到的错误。这是 Google for C++ 推荐的。
例如,对于 C99 混合声明和代码,Linux requires 至少 GCC 3.2 和 GCC 3.1 has support
【问题讨论】:
我真的不喜欢混合声明,因为它们会降低代码的可读性并导致难以看到错误。 贾斯汀,我完全不同意你的编辑。我讨厌看到可以适用于多种语言的标题(采用粗体大字体),并且不得不在屏幕上的其他位置查找以低对比度、小字体书写的标签,以便知道我是否对这个问题有话要说。仅由标签消除歧义的模糊标题是可用性的噩梦。在可用性方面,标签通常会添加信息,而不是取代它。 @Carl, @Eduardo 我认为你们都夸大了对方喜欢的风格可能导致的错误。函数作用域的变量会导致代码腐烂,因为代码被删除并且变量变得未使用,而如果不注意命名,块作用域可能会导致变量隐藏。这两个问题都被一组很好的编译器警告所捕获,但狭窄的范围仍然是优越的,因为它可以更容易地发现愚蠢的数据使用模式......这反过来又会导致更好、更易理解的代码。 @Carl:我认为这是一个概括:有时,混合声明可以使代码更具可读性;一个经常出现的例子:首先在函数体内检查函数参数的前提条件,因为,你知道 - 这是一个 pre 条件;添加另一个块(导致额外的缩进级别)只是为了这似乎有点矫枉过正,imo @Christoph, @Dan,当然总有例外的规则。我真的想以幽默的方式陈述一个相反的观点,而不是真正想就变量声明进行单方面的争论。 【参考方案1】:也许不需要,也许分离是好的?我是用 C++ 做的,它也有这个特性。
【讨论】:
【参考方案2】:几乎没有理由重写 Linux 内核来进行外观上的更改而不会提高性能。
如果代码库可以正常工作,那么为什么要出于美观的原因对其进行更改?
【讨论】:
没有必要重写任何东西。但也许应该建议在新代码中缩小变量范围。 对于整个代码库的一致性有一些话要说。 这毕竟是小脑袋的妖精(即愚蠢的一致性)。没有人比他们考虑编码标准时更小了 ;-) @Eduardo 我还没有阅读整个 Linux src,但我也是用 ANSI C 编写的。在我的代码中,我的函数很小,变量范围不能更窄。对我来说,这个功能解决了一个我从未遇到过的问题。【参考方案3】:您不需要需要混合声明和代码来限制范围。你可以这样做:
int c;
c = 1;
int d = c + 1;
在 C89 中。至于为什么这些项目没有使用混合声明(假设这是真的),很可能是“如果它没有坏就不要修复它”的情况。
【讨论】:
【参考方案4】:没有理由像这样更改代码,C99 仍然没有得到编译器的广泛支持。主要是关于便携性。
【讨论】:
“C99 仍未被编译器广泛支持” - 这是 linux 内核中的一个问题吗?例如,对于某些平台,是否可以使用 C89 编译器引导 linux+gcc? 可能不适用于 Linux 内核,因为它与 GCC 及其汇编程序相当相关,但对于许多项目来说,这是必需的。 Linux 太大了,无法重构所有代码,以至于它出于无用的原因这样做。【参考方案5】:我不记得内核代码风格指南中对此有任何禁止。但是,它确实说函数应该尽可能小,并且只做一件事。这可以解释为什么声明和代码的混合很少见。
在一个小函数中,在作用域的开头声明变量就像一种Introit,告诉你不久之后会发生什么。在这种情况下,变量声明的移动非常有限,以至于它可能没有任何效果,或者通过将吠叫者推入人群来隐藏有关功能的一些信息,可以这么说。国王的到来在他进入房间之前被宣布是有原因的。
OTOH,一个必须混合变量和代码才能可读的函数可能太大了。这是需要将函数的某些部分抽象为单独的函数(并声明为static
,以便优化器可以内联它们)的标志之一(连同过度嵌套的块、内联 cmets 和其他东西)。
将声明保留在函数开头的另一个原因:如果您需要重新排序代码中语句的执行顺序,您可能会在没有意识到的情况下将变量移出其范围,因为在函数中声明的变量的范围代码中间在缩进中不明显(除非您使用块来显示范围)。这很容易解决,所以它只是一个烦恼,但是新代码经常会经历这种转变,并且烦恼可以累积。
还有一个原因:你可能很想声明一个变量来从函数中获取错误返回码,如下所示:
void_func();
int ret = func_may_fail();
if (ret) handle_fail(ret)
完全合理的做法。但是:
void_func();
int ret = func_may_fail();
if (ret) handle_fail(ret)
....
int ret = another_func_may_fail();
if (ret) handle_other_fail(ret);
哎呀! ret
定义了两次。 “所以?删除第二个声明。”你说。但这会使代码不对称,最终会遇到更多重构限制。
当然,我自己混合声明和编码;没有理由对此持教条主义(否则你的业力可能会超越你的教条:-)。但是你应该知道伴随的问题是什么。
【讨论】:
【参考方案6】:没有任何好处。在函数开头声明所有变量(类似pascal)更加清晰,在C89中您还可以在每个作用域的开头声明变量(内部循环示例),既实用又简洁。
【讨论】:
【参考方案7】:这是一个老问题,但我会建议惯性是大多数这些项目仍然使用 ANSI C 声明规则的原因。
但是还有许多其他可能性,从有效到荒谬:
便携性。许多开源项目的工作假设是迂腐的 ANSI C 是最便携的软件编写方式。
年龄。其中许多项目早于 C99 规范,作者可能更喜欢一致的编码风格。
无知。提交早于 C99 的程序员并没有意识到混合声明和代码的好处。 (另一种解释:开发人员完全意识到潜在的权衡,并认为混合声明和语句不值得努力。我非常不同意,但很少有两个程序员会就任何事情达成一致。)
FUD。程序员将混合声明和代码视为“C++ 主义”,因此不喜欢它。
【讨论】:
以上是关于开源项目中的C99混合声明和代码?的主要内容,如果未能解决你的问题,请参考以下文章