C中的全局变量

时间:2010-10-04 02:27:42

标签: c

另一个新手问题; 在C中使用大量全局变量是不是很糟糕?我猜测答案可能是肯定的,另一方面,使用main或其他函数作为“基函数”存储指针/值与全局范围创建一个乱七八糟的指针指针等... 有什么想法吗?

6 个答案:

答案 0 :(得分:3)

全局变量的一个问题是,无论在何处使用它们,您都可能没有referential transparency。知道给定某些输入函数会产生某些输出是有好处的。

This page is a good resource由于其他几个原因导致全局变量也很糟糕。

答案 1 :(得分:2)

通常大多数程序员都希望函数为pure,这意味着函数的输出将完全由其输入决定。通过赋予它们状态,您可以为将使用您的代码的其他人引入很多混淆。这引用了函数中声明的static变量。

对于真正的全局变量(在函数之外声明的变量),这就是Ruel所说的。关于多线程,请小心。

答案 2 :(得分:1)

如果极其需要,请使用全局变量。如果您在全球范围内拥有所需的东西,那么请随意。

答案 3 :(得分:1)

纠正由令人讨厌的全局变量引起的情况就像规范化关系数据库模式的设计一样。

总是可以选择将所有全局变量集中到一个大结构中并传递该结构。但那么,有什么意义呢?

你想把它们分组成结构然后你开始发现,“嘿,我在其他结构中也需要这个信息,因为一个愚蠢的功能需要它。”然后你认为你通过合并两个结构来解决问题。然后你发现最后,你仍然坚持使用一大块结构。

为什么呢?因为像数据库规范化一样,你的结构规范化必须一致地完成,与进程(也就是你的函数)共谋。您应该构建有关您的信息的实体关系。即使你不使用oop语言编写,你仍然应该使用与oop接壤的系统分析方法。程序员 - 分析师和普通程序员之间的区别在于程序员 - 分析师执行严格的数据和项目的过程分析。然而,普通的香草程序员做了幸福快乐的编程。

例如,我想写一个例程来控制公司的打印机。有

  • 旧的带状撞击电传(圣牛!),
  • 点阵(他们还在使用那些?),
  • 色射流,
  • 灰度射流,
  • grey-lasers,
  • 色激光器
  • 传真/扫描射流和激光的组合。

这些是功能

  • 为作业请求找到合适的打印机
  • 从失败的打印机重新路由作业
  • 作业请求可以来自日程安排,桌面或传真服务器
  • 将扫描仪输出路由到传真服务器
  • 扫描墨水,颜料水平以便更换
  • 用于过时的色带类型,预测色带更换
  • 维护维护计划

简单的方法是将所有信息放入一个巨大的全局变量池中,然后将它们全部交给它们。优点是您可以自由地编写不受限制的函数 - 仅受您记住所有变量所在位置的能力的限制。或者其他人找到它们的能力。

或者,您可以简化您的生活并学习实体规范化的简单技巧。请记住,实体不仅仅是数据,还包括流程/功能。在这样的练习结束时,你会开始惊奇地发现,如果没有像c ++这样的oop语言,你到目前为止如何能够幸存下来。

让我举一个简单(可能是不完整)的实现来举例说明。当您在ER中规划项目并对其进行记录时,它可以使您的编程和增强更加轻松。在这个敏捷工程时代,您必须能够发布项目的可用部分实现。例如,您可以告诉您的项目经理以下里程碑

  • 第1周:喷墨打印机和激光打印机的可用打印机布线
  • 第2周:古老的冲击式打印机的可用打印机路由
  • 第3周:可用的扫描作业
  • 第5-7周:可用的传真作业
  • 第8周:半生不熟的工作重新安排
  • 第9周:90%烘焙工作重新路由
  • 第9-11周:半生不熟的维护

通过绘制信息和流程的模式,您将清楚地了解可用版本的构成以及下次迭代的操作。通过精心规划的模式,您会发现在情感上不可能使用全局变量。你甚至可以拥有全局变量的模式而不是非结构化的模式。保留全局化信息结构,绝对必然需要单一访问点 - 如数据库池,启动标志以避免启动已启动的进程等。

然后,除非您正在编写嵌入式代码或内核代码,否则很快就会转向使用C ++。

struct Printer{
  id,
  printType,
  location,
  *maintenance,
  *driver
}

struct Job{
  type,
  requestor,
  location
}

struct Location{
  building,
  floor,
  suite,
  lane
}

struct PrintType{
  ink,
  colour
}

struct JobStatus{
  job,
  location,
  endStatus
}

struct Maintenance{
  inkLevel,
  schedule
}

union InkLevel{
  HPDeskJetInk,
  HPLaserJetInk,
  OlivettiFabric,
  BrotherCellophane,
  etc, etc
}

enum Ink{
  FABRICImpact,
  CELLOPHANEImpact,
  INKJet,
  LASER
}

enum Colour{
  GREY,
  COLOUR
}

enum EndStatus{
  PRINTING,
  COMPLETED,
  FAILED,
  REROUTED
}

/* print will look at Job to determine the appropriate location */
JobStatus* print(job);

/* a callback to requestor indicating completion status */
JobStatus* printCallback();

/* a fax send event detected and fax function will find the appropriate server for the Job */
JobStatus* fax(job);

/* a photocopy to file job */
JobStatus* scan(job);

Maintenance* maintain(Printer);

答案 4 :(得分:0)

虽然C让您可以完全自由地宣布所有内容全局,但如果您考虑“abstract data type”,也可以用程序语言实现,那么它将帮助您进行编码和维护。

基本上,您可以在特定模块中使数据全局化,而不是将所有数据作为所有模块的静态全局数据。

答案 5 :(得分:-6)

在任何语言中使用任何全局变量都是不好的。