34

我看到的大多数使用全局变量的反对意见都是有道理的,因为它们涉及多线程、线程安全等问题。

但是在一个小的、单线程的、非操作系统的情况下,你有什么反对意见?就我而言,如果重要的话,我正在用“C”编写我的嵌入式系统。我也是该产品的唯一开发人员。

为什么消除全局变量会使我的代码更好?

(在阅读了几个回复后,我意识到我也应该指出这个系统没有动态内存分配(例如 malloc)。所有内存都是在编译时静态分配的。)

4

13 回答 13

58

它不会。

全局变量的两个基本问题只是使命名空间混乱,以及“没有人”可以“控制”它们这一事实(因此可能与多个线程发生冲突和冲突)。

就像几乎所有其他计算机编程习语一样,“全局变量很糟糕”是一个指导方针,而不是一个硬性规定。在制定这些“规则”时,最好不要简单地死记硬背地采用规则,以了解规则创建背后的环境和动机。不要盲目地接受它们。

在您的情况下,您似乎了解系统的性质和围绕规则的论点,并决定它不适用于这种情况。你是对的,它没有。

所以,不要担心。

于 2009-05-16T18:15:00.013 回答
24

全局变量不一定是坏的,就像宏不一定是坏的一样,浓缩铀也不一定是坏的。只要您对给定设计选择的利弊做出有意识的决定,就应该没问题。

一些反对全局变量的论点是:

  1. 它们违反了良好的面向对象设计
  2. 它们使您的代码难以进行单元测试,因为您无法在不设置代码期望看到的所有全局变量的情况下测试单个代码块
  3. 它们增加了代码中的耦合:一个代码块中的操作可能会通过共享全局变量以不可预知的方式影响另一块代码中的内容

全局变量一些论据:

  1. 它们使在许多功能之间共享单个资源变得容易
  2. 它们可以使代码更易于阅读

如果在您的设计中,全局变量是有意义的,并且可用于使您的代码更易于阅读或更易于维护,而不会让您自己陷入随机错误和测试难题,那么请务必使用它们。

我为嵌入式微控制器编写了很多 C 代码,并且一直使用全局变量。在这样一个僵化的系统中,全局变量是有意义的。我知道潜在的缺点,但我已经分析了优缺点,并编写了我的代码以防范主要的陷阱。

底线:没有硬性规定。只需根据您拥有的最佳信息,为您的特定项目或平台做出最佳决策。

于 2009-05-16T18:24:16.670 回答
18

这是一篇很好的文章,说明了为什么全局变量不好

为什么在不必要的时候应该避免使用全局变量?

非局部性——当单个元素的范围有限时,源代码最容易理解。全局变量可以被程序的任何部分读取或修改,因此很难记住或推理每种可能的用途。没有访问控制或约束检查——程序的任何部分都可以获取或设置全局变量,并且任何关于其使用的规则都可以很容易地被破坏或遗忘。

隐式耦合——具有许多全局变量的程序通常在其中一些变量之间存在紧密耦合,以及变量和函数之间的耦合。将耦合的项目分组为有凝聚力的单元通常会导致更好的程序。

内存分配问题——某些环境的内存分配方案使得全局变量的分配变得棘手。在“构造函数”具有分配以外的副作用的语言中尤其如此(因为在这种情况下,您可以表达两个全局变量相互依赖的不安全情况)。此外,当动态链接模块时,可能不清楚不同的库是否有自己的全局实例或全局是否共享。

测试和限制 - 使用全局变量的源代码更难测试,因为无法在运行之间轻松设置“干净”环境。更一般地,使用任何类型的未明确提供给该源的全球服务的源由于同样的原因而难以测试。

添加全局变量非常容易。很容易养成声明它们的习惯。它比思考一个好的设计要快得多。

全局变量并不像你想象的那么糟糕,只是在不必要的时候应该避免使用它们。全局变量可以很好地用于将在整个程序中使用的变量,确保您始终牢记您必须跟踪该变量发生变化的位置;但是对于那些往往只在程序的有限部分中使用的变量来说,避免让它成为全局变量是一个很好的理由。

于 2009-05-16T18:23:27.263 回答
7

因为它最大限度地减少了耦合。您的系统现在可能很小,但如果您继续工作,结果可能不是。

于 2009-05-16T18:13:14.683 回答
7

在用 C 编写的小型嵌入式应用程序中,全局变量是必需的。例如,您需要使用全局变量来在中断服务程序和另一个模块之间传递信息。这些是一些技巧,可以帮助您在嵌入式应用程序中有效地使用全局变量:

  • 区分静态变量和全局变量。静态变量可以在同一个 C 文件中的所有函数中使用。它们相当于 C++ 类中的私有成员。在 C 语言中,您必须自己完成编译器的工作。使用 static 关键字来避免在模块外部意外使用变量并明确其范围。您可能希望在变量前面加上模块名称。

  • 遵循全局变量的命名约定(许多 C 文件使用)。清楚地表明它们是全球性的。

  • 如果您需要大量全局变量,请考虑将它们捆绑在一个结构中。

  • 必要时使用 volatile 关键字。如果全局变量被 ISR 修改,则需要这样做。

于 2009-05-18T09:34:35.953 回答
5

使用全局变量的代码更难维护。因为维护者必须先找到系统中变量的每一次使用,然后才能准确地知道变量的作用。由于这会减慢维护速度,因此应尽可能避免。就是这样`

于 2009-07-19T20:05:00.850 回答
2

这是范围的问题。我们有喜欢制作全局变量来执行本地概念的开发人员。它使这些变量的使用更难跟踪,因此在使用它们时更容易出错。

你也可以把你的钱包放在你的前廊上,但是你对谁在访问它的控制要少得多。

话虽如此,全局变量有一些有效的用途,但就像任何其他值得遵循的规则一样。这是例外而不是正常情况。他们非常现有的指出,他们有一个用途。

如果您决定使用全局变量,请尝试对它们进行良好的注释并给它们起好名字。当人们制作像“bool bIsFound”这样的全局变量时,我真的很困扰。

我们强调在代码审查中评估每个新的全局变量,看看是否有更好的方法。

于 2009-05-16T18:27:08.410 回答
1

简短的回答是,全局变量在历史上一直是微妙错误的来源。但是后来(戴上我的函数式程序员的帽子)所有变量都成为了细微错误的来源。

基本上,全局变量意味着您无法使用变量的值查看一段代码,并且在不知道过去设置该变量值的所有其他代码段的情况下知道它将做什么。

于 2009-05-16T18:23:18.560 回答
1

在您的情况下,全局变量可能还不错。另一方面,你需要它们吗?使用它们你能得到什么?

即使在您的情况下,全局变量也使弄清楚应用程序的状态变得更加困难。这可能会阻碍调试,并可能导致细微的错误。

全局变量也使测试更加困难。它们添加了对您可能希望在测试期间避免的外部代码的依赖。

但最后,在用 C 编程时,全局变量是很难避免的。在更高级的语言中,全局变量在大多数情况下是毫无意义的。使用它们不会使您的代码更清晰。

在 C 语言中,有很多情况下全局变量只是最好、最简单和最干净的解决方案。

因此,在您的情况下,请根据具体情况进行处理。您可能最终会拥有一些全局变量,但不要将变量设为全局变量,除非您确定它实际上是最好的解决方案,不仅是现在,而且在一年后您必须调试代码或制作应用程序时多线程。

于 2009-05-16T19:22:01.913 回答
0

对于全局变量,通常很难知道它们在何处或何时更新,以及哪些代码更新了该变量。无法控制谁可以更新它或以何种方式更新变量。

如果你的应用程序很小,跟踪起来并不难——但是你的应用程序变得越大,你拥有的全局变量越多,应用程序代码就越像意大利面条。

简而言之 - 它成为维护和调试的噩梦。

于 2009-05-16T18:13:23.683 回答
0

问题是跟踪你的最后一个代码的哪一点修改了全局的状态。通常,您希望将变量保持在尽可能小的范围内,以便您可以更轻松地推理它们。

于 2009-05-16T18:13:45.057 回答
0

想到的一个原因是未来的证明。您现在可能是您产品的唯一开发人员,但可以想象其他人会在以后维护它。当然,在您的特定情况下,这可能不是真的。

虽然您的产品现在可能又小又整齐——使用全局变量不会使整体设计复杂化或损害可读性——谁说产品不会变得更大或不会被合并到另一个产品中?上帝禁止另一个维护者/开发者来解决你对全局变量的使用。

当然,您现在可以决定使用全局变量,当项目看起来变得更加复杂时,您可以返回并重写其中的一部分,但是为什么要强迫自己做这些额外的工作呢?你更有可能(如果你还记得全局变量的话)认为做这项工作太费力了,然后放手设计:此时你有麻烦了!

所以,省去自己的头痛,着眼于未来的设计。现在所需的工作可能会使将来的生活更轻松。

如果这不能说服你,想象一下作为这个项目的开发人员,他们的代码在最高法院面前被发现有错误和错误的编程实践:有缺陷的呼吸测试代码反映了源代码审查的重要性

于 2009-05-16T18:14:23.947 回答
0

将大多数变量保持在本地并缩小其范围有助于促进更好的编程实践。它还降低了错误地更改变量和必须通过函数来​​寻找意外或不明显后果的风险。我相信它还使代码更易于阅读和维护,因为与特定代码部分相关的大多数变量都是在附近定义和初始化的。否则,我似乎一直在回顾定义所有 gobals 的代码部分。我确实使用了一些全局变量,但主要用于将配置信息传递给子模块。

于 2009-05-16T18:18:55.433 回答