我正在C中建造一个Minishell,并且已经进入了一个障碍,似乎可以通过使用全局变量(准确地说)可以很容易地修复它。我认为全球性的原因是,替代方法是将这些变量传递给我程序中的几乎每个功能。
变量为mainargc,mainargv和shiftedmargv。前两个是参数的数量,分别传递给MAIN的参数列表。变量shiftedmargv是参数列表,但是它可能已移动。我正在尝试创建内置功能变化和解开,并将ShiftedMargv指向不同的参数。
那么,将这些全球化是愚蠢的吗?否则,我将不得不修改大量的代码,我不确定我会通过使它们全局而丢失任何东西。
如果我确实使它们全球化,那么从主标题文件中这样做是愚蠢的?
感谢您的帮助人员,如果您需要任何澄清,请提出任何要求。
作为全局变量的替代方案,请考虑'全局函数':
extern int msh_mainArgC(void);
extern char **msh_mainArgV(void);
extern char **msh_shiftedArgV(void);
这些功能的实现是微不足道的,但是它允许您控制对内存的访问。而且,如果您需要做一些幻想,则可以更改功能的实现。(我选择资本化C和V以使差异更加明显;仅当8-12字母名称的最后一个字符不同时,很难发现差异。)
将有一个实现文件可以定义这些功能。在该文件中,将有存储相关信息的静态变量,以及可以设置和以其他方式操纵变量的功能。原则上,如果您将足够的const
预选赛敲打,则可以确保调用代码不能通过旨在执行此操作的功能(或使用铸件来删除const-ness)来修改数据。
这是否值得您有争议。但这可能是。这是一种更加"面向对象的"操作风格。这是考虑然后丢弃的替代方法,而不是留下未经想象的东西。
请注意,使用这些功能的子系统可能具有收集全局值的一个函数,然后将其传递给其从属函数。这使下属不必知道值的来源;仅正确地与它们一起工作。如果有全局变量,您必须担心混叠 - 是传递的函数值(全局变量的副本),但它也访问了全局变量。有了功能,您不必以相同的方式担心。
我会说这不是愚蠢的,但是你应该谨慎行事。
通常避免全球的原因不是应该使用它们,而是他们的用法使人们经常导致程序员崩溃和燃烧。通过经验,人们了解何时是正确的时间和何时是错误的时间之间的区别。
如果您对问题进行了深入的思考,您正在尝试解决并考虑您为解决此问题而写的代码,并考虑了此代码的未来(即,您是否损害了可维护性)并认为全局是不可避免的,要么更好地代表编码的解决方案,然后您应该使用全局。
稍后,您可能会崩溃并燃烧,但是这种经验将帮助您稍后辨别更好的选择。相反,如果您觉得不使用全球群体可能会导致崩溃和振动,那么这是您先前的经历,说您应该使用它们。您应该相信这种本能。
dijkstra有一篇论文,他讨论了goto
陈述可能造成的伤害,但在我看来,他的讨论也解释了我们在全球群体中的一些困难。可能值得一读。
这个答案和此答案也可能使用。
全球范围都可以,只要它们以逻辑方式是全球性的,而不是只是使您的生活更轻松的卑鄙。例如,Globals可以描述您的程序执行或用另一种词的属性进行的环境。我曾经与之合作过的所有复杂软件都有一组明确的全球范围。这没什么错。它们的范围从少数到大约十几个。在后一种情况下,它们通常在逻辑上以结构进行分组。
Globals通常以外部为外部文件,然后在源文件中定义。只需记住,在线程之间共享全球,因此必须受到保护,除非使用线程本地存储声明它们更有意义。
对于外壳,您的状态比这更多。您具有重新映射的文件描述符的状态(由于各种原因,您需要跟踪),trap
处置,set
选项,环境和外壳变量,...
通常,全局变量是错误的解决方案。取而代之的是,所有状态都应保持在某种形式的上下文结构中,该指针到处都是。这是一个很好的程序设计,通常允许您在同一过程中运行相同代码的多个实例(例如,多个解释器,多个视频解码器等)。
。话虽如此,外壳是一个非常特殊的情况,因为它也处理了的全球状态,您无法保持结构:信号处置,文件描述符和映射符,儿童流程,过程组,控制终端等。可以用额外的层抽象很多其中,以便您可以模仿所需的行为,同时保持单个过程中可能存在多种多样的清洁上下文,但这是一个非常多的比编写传统外壳更艰巨。因此,我可能会给自己一些余地,以使用全局变量写出"懒惰的方式"。但是,如果这是一项学习练习,请尝试仔细识别每次介绍全局变量或状态,为什么这样做以及如何在没有全球状态的情况下以不同的方式实施该程序。这将来对您非常有用。