使C模块变量可以只读方式访问

我想为模块变量提供客户端模块的只读访问权限。 几种解决方案

1 。 最常见的一个:

// module_a.c static int a; int get_a(void) { return a; } // module_a.h int get_a(void); 

这使得每个变量共享一个函数,一个函数调用(我正在考虑执行时间和可读性),每个读取一个副本。 假设没有优化链接器。

2 。 另一种方案:

 // module_a.c static int _a; const int * const a = &_a; // module_a.h extern const int * const a; // client_module.c int read_variable = *a; *a = 5; // error: variable is read-only 

我喜欢这样,除了客户端需要读取指针内容的事实。 此外,每个只读变量都需要其指向const extern const指针。

3 。 受第二个解决方案启发的第三个解决方案是隐藏结构后面的变量和结构的外部指针。 在我看来,符号module_name->a在客户端模块中更具可读性。

4 。 我可以为get_a(void)函数创建一个内联定义 。 它仍然看起来像客户端模块中的函数调用,但应该进行优化。

我的问题:

  • 有没有一种最好的方法可以在模块中修改变量,只能在其他模块中以只读方式访问? 什么方面最好?

  • 您接受或拒绝使用上述哪种解决方案,为什么?

我知道这是微观优化 – 我可能没有实现它 – 但我仍然对这种可能性感兴趣,最重要的是知道。

关于选项#4,如果在实现文件之外无法访问该变量,我不确定是否可以使其内联。 我不认为选项#2和#3是真正的只读。 指针可以抛弃常量并进行修改(const只是编译器“警告”,没有具体内容)。 只有选项#1是只读的,因为它返回一个副本。

对于与变量访问相同的速度,您可以在内联函数中定义外部变量:

 static inline int get_a(void) { extern int a_var; return a_var; } 

这很简单,也很清楚。 其他选项似乎不必要地复杂化。

编辑:我假设你为你的名字使用前缀,因为你写了C.所以它实际上是:

 extern int my_project_a; 

这可以防止客户端意外地使用相同的名称创建变量。 但是,如果客户端故意生成具有相同名称的变量,该怎么办? 在这种情况下, 你已经输了 ,因为客户要么是1)积极地试图破坏你的图书馆,要么2)无能力超出合理的住宿范围。 在情况#1中,没有什么可以阻止程序员。 在情况#2中,程序将被打破。

尝试在您的系统上运行nm /lib/libc.so或等效项。 您将看到大多数libc实现都有几个未在头文件中定义的变量。 在我的系统上,这包括__host_byaddr_cache类的__host_byaddr_cache 。 C库实现者不负责照顾我并阻止我运行:

 extern void *__host_byaddr_cache; __host_byaddr_cache = NULL; 

如果你开始认为你必须强迫客户将你的变量视为只读,那么你正走在无果的偏执的道路上。 static关键字实际上只是方便将对象保留在全局命名空间之外,它不是也不是防止外部访问的安全措施。

强制执行只读变量的唯一方法是管理客户端代码 – 通过在VM中沙箱或通过算法validation它无法修改您的变量。

  1. 最常见的一个:

这是最常见的原因。 这是最好的一个。

在大多数情况下,我不认为性能受到重大影响值得担心。