c 访问不同翻译单元中的数据成员

c accessing data members in different translation unit

我写了一些代码,使用函数指针指向 link c 中的模块函数。我想知道是否可以使用这些函数指针来访问另一个翻译单元中的状态。

我写了这个结构来处理生命周期函数,这样我就可以让一个模块做所有事情,你用你的函数传入一个指向这个结构的指针,它们会在它们应该调用的时候被调用。

typedef struct {
    void (*init_func_ptr)(void);
    void (*fixed_update_func_ptr)(void);
    void (*variable_update_func_ptr)(double alpha);
    void (*variable_render_func_ptr)(double alpha);
    void (*pause_func_ptr)(void);
    void (*resume_func_ptr)(void);
    void (*resize_func_ptr)(int width, int height);
    void (*handle_event_func_ptr)(key_event *e);
    void (*quit_func_ptr)(void);
} lifecycle_ptrs;

我通常这样设置

    lifecycle_ptrs* ptrs;

    ptrs = calloc(1, sizeof(lifecycle_ptrs));
    ptrs->init_func_ptr = &init;
    ptrs->fixed_update_func_ptr = &fixed_update;
    ptrs->variable_update_func_ptr = &variable_update;
    ptrs->variable_render_func_ptr = &variable_render;
    ptrs->pause_func_ptr = &pause;
    ptrs->resume_func_ptr = &resume;
    ptrs->resize_func_ptr = &resize;
    ptrs->handle_event_func_ptr = &handle_events;
    ptrs->quit_func_ptr = &quit;

这个 ptrs 结构在定义 main 的模块中设置,并作为函数参数传递。一旦通过,程序将进入无限循环,直到用户请求退出。

到目前为止,这工作得很好并且可以做我想做的事情。

我现在很好奇的是,有没有可能有这样的东西,我可以从另一个模块访问变量?

假设模块 a 看起来像这样

modulea.c
int a;
int b;
char t[] = "test";

moudleb.c
struct t;
float 12.0;

是否可以从模块b访问模块a的成员变量,反之亦然?

我可以编写函数来获取每样东西,但我觉得可能有更优雅和更易于维护的方法来做到这一点。我还可以定义一个结构并执行一个交换函数,其中模块 a 可以访问模块 b 中的变量,反之亦然,但这对我来说似乎有点奇怪。

还有其他方法吗?我更关心可维护性,但任何见解都会有所帮助,因为现在我不知所措。

是的,技术上是可行的,只需使用 extern

但是,您没有理由这样做。如果您曾经想过需要访问另一个文件中的(非常量)变量,那么这意味着您的程序设计被破坏了。

如果你完成 extern,它会变得更破烂,你会得到完整的意大利面条代码,耦合非常紧密,程序中的所有内容都依赖于其他所有内容,所有错误都会失败-升级程序并拆除与错误完全无关的东西。

所以正确的解决方法是退后一步,对整个程序设计进行三思。

使用面向对象设计并编写每个 h 和 c 文件对,使它们一起形成一个自治模块(称其为 class、ADT 或任何您喜欢的),而不是这种意大利面条式编码只关心它自己指定的目的。此类 c 文件中的所有文件范围变量都应声明为 static 以阻止来自外部的访问。如果需要的话,访问这些变量应该通过 setter/getter 函数来完成。唯一可以直接跨文件共享的变量是只读常量。

但请注意,您应尽可能避免使用文件范围变量,因为它们会使代码不可重入。

在不同 模块之间共享成员的最简单方法是使用头文件。

您可以将 modulea.h 文件添加到您的项目中,例如:

#ifndef modulea_H_
#define modulea_H_

extern int a;
extern int b;
extern char t[];

#endif

然后您可以 #include "modulea.h" 在您的 moduleb.c 源文件中。