开源项目中的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混合声明和代码?的主要内容,如果未能解决你的问题,请参考以下文章

开源项目的版权声明已无存在必要? | Linux 中国

如何给自己的开源项目选择和添加 License

Vue在线客服系统开源项目

优秀开源项目之二:流媒体直播系统Open Broadcaster Software

C++开源项目:十行代码15个BUG,你入坑了吗?

资源 | Struts开源框架(入门+精通)