防止全局变量在初始化后被修改的唯一方法是声明它const:
const int i = 5;
但是,如上所示,这需要使用定义对其进行初始化。除了在编译时求值的常量表达式之外,没有办法从程序代码初始化它。
请注意,虽然您可以将 const 丢弃,但这会导致 undefined bahaviour 并且很可能会导致问题,因为 const 变量可能会被放入 read-只有你的程序的内存区域。
如果您确实需要对此类变量进行访问控制,则必须将其作为 static 放入函数中(在第一次调用时进行初始化),或者 - 最好是单独的模块/编译单元(也称为static)。然后在此使用显式 setter/getter 函数:
"wrapper.h":
#ifndef WRAPPER_H
#define WRAPPER_H
extern void set_once(int v);
extern int get_value(void);
#endif
"wrapper.c":
#include <stdbool.h>
#include "wrapper.h"
static struct {
bool is_set; // guaranteed false on startup
int value;
} my_var;
void set_once(int v)
{
if ( !my_var.is_set )
my_var.value = v;
else
; // report an error, e.g. abort()
}
int get_value(void)
{
if ( !my_var.is_set )
return my_var.value;
// report an error, e.g. abort()
}
"main.c"
#include "wrapper.h"
int main(void)
{
set_once(5);
int i = get_value();
}
这样,如果您使用未初始化的值或尝试多次设置它,您将收到运行时错误。请注意,该标志依赖于将全局变量初始化为 0(保证评估 false)。
尽管您可能只是忽略了多个集合,但至少在调试/测试期间(例如使用 assert)是捕获和报告的好习惯。
编辑:
上述方法适用于全局变量。如果要保护多个变量,可以对其进行修改,例如函数采用指向结构的指针。如果要使用不同的类型,请将标志打包到自己的结构中,并将其作为第一个匿名字段添加到每个要保护的类型的结构类型中。如果 gcc 扩展可用且允许,请查看 -fplan9-extensions。使用不透明指针可以避免意外的外部修改。
但是,对于局部变量,请使用 @MattMcNabb 的版本。