我想为模块变量提供客户端模块的只读访问权限。 几种解决方案:
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
我喜欢这样,除了客户端需要读取指针内容的事实。此外,每个只读变量都需要extern const
指向const
的指针。
第3 即可。受第二个解决方案启发的第三个解决方案是隐藏结构后面的变量和结构的外部指针。在我看来,符号module_name->a
在客户端模块中更具可读性。
4 即可。我可以为get_a(void)
函数创建内联定义。它仍然看起来像客户端模块中的函数调用,但应该进行优化。
我的问题:
是否有最好的方法可以在其他模块中以只读方式访问模块中修改变量?什么方面最好?
您接受或拒绝使用上述哪种解决方案?为什么?
我知道这是微观优化 - 我可能没有实现它 - 但我仍然对这种可能性感兴趣,最重要的是知道。
答案 0 :(得分:5)
关于选项#4,如果在实现文件之外无法访问该变量,我不确定是否可以使其内联。我不认为选项#2和#3是真正的只读。指针可以抛弃并修改常量(const只是编译器“警告”,没有具体内容)。只有选项#1是只读的,因为它返回一个副本。
答案 1 :(得分:2)
对于与变量访问相同的速度,您可以在内联函数中定义外部变量:
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
之类的内容。 C库实现者不负责照看我并阻止我运行:
extern void *__host_byaddr_cache;
__host_byaddr_cache = NULL;
如果您开始认为必须强制客户端将您的变量视为只读,那么您正走在无果而终的偏执之路上。 static
关键字实际上只是方便将对象保留在全局命名空间之外,它不是也不是防止外部访问的安全措施。
强制执行只读变量的唯一方式是管理客户端代码 - 通过在VM中沙箱化或通过算法验证它无法修改变量。
答案 2 :(得分:1)
- 最常见的一个:
醇>
这是最常见的原因。这是最好的一个。
在大多数情况下,我并不认为性能影响值得足以值得担心。