如何在内在具有状态的程序中避免使用全局变量?
通过传递参数...
struct state {
int some_value;
};
int state_init(struct state *s);
int state_fini(struct state *s);
int state_set_value(struct state *s, int new_value);
int state_get_value(struct state *s, int *value);
#include "state.h"
int state_init(struct state *s) {
s->some_value = -1;
return 0;
}
int state_fini(struct state *s) {
return 0;
}
int state_set_value(struct state *s, int value) {
if (value < 0) {
return -1;
}
s->some_value = value;
return 0;
}
int state_get_value(struct state *s, int *value) {
if (s->some_value < 0) {
return -1;
}
*value = s->some_value;
return 0;
}
#include "state.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
struct state state;
int err = state_init(&state);
if (err) abort();
int value;
err = state_get_value(&state, &value);
if (err != 0) {
printf("Getting value errored: %d\n", err);
}
err = state_set_value(&state, 50);
if (err) abort();
err = state_get_value(&state, &value);
if (err) abort();
printf("Current value is: %d\n", value);
err = state_fini(&state);
if (err) abort();
}
唯一需要使用全局变量(最好只有一个指向某些堆栈变量的指针)的情况是信号处理程序。标准方法是在信号处理程序中仅增加一个类型为
sig_atomic_t
的单个全局变量,并且不执行任何其他操作-然后通过检查该变量的值从代码的其余部分中正常流程执行所有与信号处理相关的逻辑。(在POSIX系统上)内核的所有其他异步通信,如
timer_create
,它们可以通过使用
union sigval
中的成员向通知函数传递参数。
您认为这些规则足以长期避免全局变量地狱吗?
主观上:不。我相信一个潜在的未受教育的程序员在给定第一条规则时在创建全局变量方面拥有太多自由。在
复杂程序中,我会使用硬性规则:不要使用全局变量。如果在研究了所有其他方式和所有其他可能性之后,您必须使用全局变量,请确保全局变量留下尽可能小的内存印记。
在简单的短程序中,我不会太在意。
文件范围变量有多糟糕?
这是基于观点的 - 在一些项目中使用许多全局变量是可以接受的。我相信这个主题在全局变量是否有害和其他许多互联网资源中已经详细讨论过。
使用extern从其他文件读取变量是可以的吗?
是的,可以。
没有“硬性规定”,每个项目都有自己的规则。我也建议阅读c2 wiki 全局变量是否有害。
extern
变量只会导致混淆。此外,尝试通过命名约定清楚地区分全局变量。 - Peter