开源项目中C99混合声明和代码?

发布于 2024-09-04 23:26:15 字数 656 浏览 1 评论 0原文

为什么C99混合声明和代码仍然不可用用于开源 C 项目,例如 Linux 内核GNOME

我真的很喜欢混合声明和代码,因为它使代码更具可读性,并通过将变量的范围限制在最窄的范围来防止难以发现的错误。这是 Google C++ 推荐的做法。

例如,Linux 至少需要 GCC 3.2 和 GCC 3.1 支持 C99 混合声明和代码

Why is still C99 mixed declarations and code not used in open source C projects like the Linux kernel or GNOME?

I really like mixed declarations and code since it makes the code more readable and prevents hard to see bugs by restricting the scope of the variables to the narrowest possible. This is recommended by Google for C++.

For example, Linux requires at least GCC 3.2 and GCC 3.1 has support for C99 mixed declarations and code

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

孤独陪着我 2024-09-11 23:26:16

也许不需要,也许分开也好?我用C++做的,C++也有这个功能。

Maybe it's not needed, maybe the separation is good? I do it in C++, which has this feature as well.

一抹苦笑 2024-09-11 23:26:16

没有理由像这样改变代码,而且 C99 仍然没有得到编译器的广泛支持。这主要是关于便携性。

There is no reason to change the code away like this, and C99 is still not widely supported by compilers. It is mostly about portability.

樱娆 2024-09-11 23:26:15

不需要需要混合声明和代码来限制范围。你可以这样做:

{
  int c;
  c = 1;
  {
    int d = c + 1;
  }
}

在C89中。至于为什么这些项目没有使用混合声明(假设这是真的),很可能是“如果它没有损坏,就不要修复它”的情况。

You don't need mixed declaration and code to limit scope. You can do:

{
  int c;
  c = 1;
  {
    int d = c + 1;
  }
}

in C89. As for why these projects haven't used mixed declarations (assuming this is true), it's most likely a case of "If it ain't broke don't fix it."

2024-09-11 23:26:15

这是一个老问题,但我认为惯性是大多数项目仍然使用 ANSI C 声明规则的原因。

然而,还有许多其他可能性,从有效到荒谬:

  • 可移植性。许多开源项目都假设迂腐的 ANSI C 是编写软件的最可移植的方式。

  • 年龄。其中许多项目早于 C99 规范,作者可能更喜欢一致的编码风格。

  • 无知。提交早于 C99 的程序员并没有意识到混合声明和代码的好处。 (另一种解释:开发人员充分意识到潜在的权衡,并认为混合声明和声明不值得付出努力。我非常不同意,但很少有两个程序员会在任何事情上达成一致。)

  • FUD。程序员将混合声明和代码视为“C++ 主义”,并因此不喜欢它。

This is an old question but I'm going to suggest that inertia is the reason that most of these projects still use ANSI C declarations rules.

However there are a number of other possibilities, ranging from valid to ridiculous:

  • Portability. Many open source projects work under the assumption that pedantic ANSI C is the most portable way to write software.

  • Age. Many of these projects predate the C99 spec and the authors may prefer a consistent coding style.

  • Ignorance. The programmers submitting predate C99 and are unaware of the benefits of mixed declarations and code. (Alternate interpretation: Developers are fully aware of the potential tradeoffs and decide that mixed declarations and statements are not worth the effort. I highly disagree, but it's rare that two programmers will agree on anything.)

  • FUD. Programmers view mixed declarations and code as a "C++ism" and dislike it for that reason.

为你拒绝所有暧昧 2024-09-11 23:26:15

没有理由重写 Linux 内核来进行外观上的更改,而不会带来任何性能提升。

如果代码库可以正常工作,那么为什么要出于美观原因而更改它呢?

There is little reason to rewrite the Linux kernel to make cosmetic changes that offer no performance gains.

If the code base is working, so why change it for cosmetic reasons?

八巷 2024-09-11 23:26:15

没有任何好处。在函数的开头声明所有变量(类似 pascal)更加清晰,在 C89 中,您还可以在每个作用域的开头声明变量(内部循环示例),这既实用又简洁。

There is no benefit. Declaring all variables at the beginning of the function (pascal like) is much more clear, in C89 you can also declare variables at the beginning of each scope (inside loops example) which is both practical and concise.

夏花。依旧 2024-09-11 23:26:15

我不记得内核代码风格指南中有任何对此的禁止。然而,它确实说函数应该尽可能小,并且只做一件事。这可以解释为什么声明和代码的混合很少见。

在一个小函数中,在作用域开始处声明变量就像一种Introit,告诉您有关即将发生的事情的信息。在这种情况下,变量声明的移动非常有限,以至于它可能没有任何效果,或者可以通过将叫喊者推入人群来隐藏一些有关功能的信息。国王在进入房间之前就宣布他的到来,这是有原因的。

OTOH,一个必须混合变量和代码才能可读的函数可能太大了。这是函数的某些部分需要抽象为单独的函数(并声明为静态的,以便优化器可以内联)的标志之一(以及过度嵌套的块、内联注释和其他东西)。他们)。

将声明保留在函数开头的另一个原因:如果您需要重新排序代码中语句的执行顺序,您可以将变量移出其作用域而没有意识到它,因为在代码中间声明的变量的作用域在缩进中并不明显(除非您使用块来显示范围)。这很容易修复,所以这只是一种烦恼,但新代码经常经历这种转换,而且烦恼可能会累积。

另一个原因:您可能会想声明一个变量来从函数中获取错误返回代码,如下所示:这是

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 定义了两次。 “那么?删除第二个声明。”你说。但这会使代码不对称,最终会遇到更多重构限制。

当然,我自己混合声明和代码;没有理由对此保持教条(否则你的业力可能会超越你的教条:-)。但您应该知道随之而来的问题是什么。

I don't remember any interdictions against this in the style guide for kernel code. However, it does say that functions should be as small as possible, and only do one thing. This would explain why a mixture of declarations and code is rare.

In a small function, declaring variables at the start of scope acts as a sort of Introit, telling you something about what's coming soon after. In this case the movement of the variable declaration is so limited that it would likely either have no effect, or serve to hide some information about the functionality by pushing the barker into the crowd, so to speak. There is a reason that the arrival of a king was declared before he entered a room.

OTOH, a function which must mix variables and code to be readable is probably too big. This is one of the signs (along with too-nested blocks, inline comments and other things) that some sections of a function need to be abstracted into separate functions (and declared static, so the optimizer can inline them).

Another reason to keep declarations at the beginning of the functions: should you need to reorder the execution of statements in the code, you may move a variable out of its scope without realizing it, since the scope of a variable declared in the middle of code is not evident in the indentation (unless you use a block to show the scope). This is easily fixed, so it's just an annoyance, but new code often undergoes this kind of transformation, and annoyance can be cumulative.

And another reason: you might be tempted to declare a variable to take the error return code from a function, like so:

void_func();
int ret = func_may_fail();
if (ret) { handle_fail(ret) }

Perfectly reasonable thing to do. But:

void_func();
int ret = func_may_fail();
if (ret) { handle_fail(ret) }
....
int ret = another_func_may_fail();
if (ret) { handle_other_fail(ret); }

Ooops! ret is defined twice. "So? Remove the second declaration." you say. But this makes the code asymmetric, and you end up with more refactoring limitations.

Of course, I mix declarations and code myself; no reason to be dogmatic about it (or else your karma may run over your dogma :-). But you should know what the concomitant problems are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文