2

我正在用 C 语言构建一个 minishell,并且遇到了一个障碍,似乎可以通过使用全局变量(准确地说是 3 个)来轻松修复它。我认为全局变量是必要的原因是,替代方法是将这些变量传递给我程序中的几乎每个函数。

变量是 mainargc、mainargv 和 shiftMArgV。前两个分别是参数的数量和传递给 main 的参数列表。变量shiftedMArgV 是参数列表,但它可能已被移位。我正在尝试创建内置函数 shift 和 unshift,并使 shiftMArgV 指向不同的参数。

那么,让这些全球性的东西是愚蠢的吗?否则我将不得不修改大量的代码,而且我不确定通过使它们全球化我会失去任何东西。

如果我确实将它们设为全局,那么从主头文件中这样做会很愚蠢吗?

感谢大家的帮助,如果您需要任何澄清,请询问。

4

5 回答 5

5

作为全局变量的替代方案,请考虑“全局函数”:

extern int    msh_mainArgC(void);
extern char **msh_mainArgV(void);
extern char **msh_shiftedArgV(void);

这些函数的实现是微不足道的,但它允许您控制对内存的访问。如果你需要做一些花哨的事情,你可以改变函数的实现。(我选择将 C 和 V 大写以使差异更加明显;当 8-12 字母名称的最后一个字符不同时,很难发现差异。)

会有一个定义这些函数的实现文件。在该文件中,将有存储相关信息的静态变量,以及用于设置和以其他方式操作变量的函数。原则上,如果您使用足够多的const限定符,您可以确保调用代码不能修改数据,除非通过设计用于这样做的函数(或使用强制转换来删除 const-ness)。

这对你来说是否值得值得商榷。但它可能是。它是一种更接近“面向对象”的操作方式。这是一种考虑然后丢弃的替代方案,而不是不考虑的事情。

请注意,使用这些函数的子系统可能有一个函数来收集全局值,然后将这些值传递给它的从属函数。这使下属不必知道值的来源;只需正确操作即可。如果有全局变量,您必须担心别名 - 是一个函数传递值(全局变量的副本),但它是否也访问全局变量。使用这些功能,您不必以同样的方式担心。

于 2012-11-03T22:29:24.190 回答
2

我想说这并不愚蠢,但你应该谨慎行事。

通常避免使用全局变量的原因不是它们永远不应该被使用,而是它们的使用导致人们经常导致程序员崩溃和烧毁。通过经验,人们可以了解何时是正确的时间和何时是错误的时间之间的区别。

如果您对您要解决的问题进行了深入思考,并考虑了您为解决此问题而编写的代码,并且还考虑了该代码的未来(即您是否会损害可维护性)并认为全局是不可避免的或更好的表示编码解决方案,那么您应该使用全局。

稍后,您可能会崩溃和燃烧,但这种经历将帮助您以后辨别可能是更好的选择。相反,如果您觉得不使用全局变量可能会导致崩溃和烧毁,那么您之前的经验就是说您应该使用它们。你应该相信这种直觉。

Dijkstra 有一篇论文讨论了该goto声明可能造成的危害,但在我看来,他的讨论也解释了我们在使用全局变量时遇到的一些困难。它可能值得一读。

这个答案这个答案也可能有用。

于 2012-11-03T22:18:42.330 回答
1

对于 shell,你有比这更多的状态。您拥有重新映射的文件描述符的状态(出于各种原因需要对其进行跟踪)、trap配置、set选项、环境和 shell 变量,...

一般来说,全局变量是错误的解决方案。相反,所有状态都应该保存在某种上下文结构中,一个指向它的指针到处传递。这是一个很好的程序设计,通常它允许您在同一个进程中运行相同代码的多个实例(例如多个解释器、多个视频解码器等)。

话虽如此,shell是一个非常特殊的情况,因为它也处理了很多您无法将全局状态保存在一个结构中:信号处置、文件描述符和映射、子进程、进程组、控制终端等。可以使用额外的层来抽象其中的很多内容,以便您可以模拟所需的行为,同时保持可能存在于单个进程中的多个干净的上下文,但这比编写传统的 shell 要困难得多。因此,我可能会给自己一些余地来使用全局变量“懒惰地”编写你的 shell。但是,如果这是一个学习练习,请尝试在每次引入全局变量或状态时仔细识别,为什么要这样做,以及如何在没有全局状态的情况下以不同的方式实现程序。这对您将来非常有用。

于 2012-11-04T00:51:54.243 回答
1

全局变量是可以的,只要它们在逻辑上是真正的全局变量,而不仅仅是让你的生活更轻松的手段。例如,全局变量可以描述程序执行的环境,或者换句话说,与应用程序的系统级别相关的属性。

于 2012-11-03T22:12:49.463 回答
1

我曾经使用过的几乎所有复杂软件都有一组明确定义的全局变量。这没什么不好。它们的范围从少数到大约十几个。在后一种情况下,它们通常按逻辑分组在结构中。

全局变量通常作为外部变量在头文件中公开,然后在源文件中定义。请记住,全局变量在线程之间共享,因此必须受到保护,除非使用线程本地存储声明它们更有意义。

于 2012-11-03T22:15:23.280 回答