2

我有一个全局变量结构:

typedef struct {
    int myvar1;
    int myvar2;
    int myvar3;
    ...
    int myvar10;
} t_myStruct myGlobalData;

我无法避免这种全局结构,所以我必须使用它。我有三个使用它的选项:

  • 在任何函数中使用“原样”全局变量。IE:

    int myFunc(void) {
        myGlobalData.myvar1 = ...
        myGlobalData.myvar10 = myGlobalData.myvar5 + ...
    }
    
  • 声明一个本地指针并使用它:

    int myFunc(void) {
        t_myStruct * p;
    
        p = &myGlobalData;
        p->myvar1 = ...
        ...
        p->myvar10 = p->myvar5 + ...
    }
    
  • 使用 local var 然后复制到全局结构:

    int myFunc(void) {
        t_myStruct localStruct;
    
        localStruct.myvar1 = ...
        localStruct.myvar10 = localStruct.myvar5 + ...
        myGlobalData = localStruct ;
    }
    

可以解释一下一般来说什么是最好的方法,为什么?

4

3 回答 3

10

选择更多的抽象。如果您可以将参数更改为myFunc,则进行其签名:

int myFunc(t_myStruct *arg)
{
    arg->myvar1 = ...

现在函数本身根本不依赖于全局变量的存在。对于需要在struct这种类型的 a 上操作的任何其他功能也是如此。如果必须使用全局变量,则尽可能隔离它的使用,即在尽可能少的地方使用全局变量。

如果您无法更改函数签名,我会从您的问题中选择最直接的选项:第一个。直接对全局变量进行操作即可。

于 2012-09-18T16:16:18.943 回答
2

在您列出的三个选项中,IMO,第一个是最好的。只需小心使用全局结构即可。

第一个和第二个选项几乎相同,但是每当您开始不必要地使用指针时,事情就会变得混乱,人们往往会犯更多的错误。

第三种选择只是一个坏主意。现在您希望每个函数都确保在完成后写回数据?如果函数A()和函数B()都在对全局结构进行编辑怎么办?A()完成后放回数据,然后B()第二次完成并覆盖A()数据?现在你需要额外的保护机制......这只是一个坏主意。

于 2012-09-18T17:10:13.867 回答
2

首先,为什么它如此不可避免?其次,为什么只有这三个选项?

如果您必须访问全局,您的第一个选择并非不合理 - 它已经是全局的,它还能变得更糟吗?

您的第二个选择完全没有意义。

您的第三个选项也没有什么优点,并且 memcpy 是不必要的,您可以直接分配一个结构:

myGlobalData = localStruct ;

在多线程应用程序中,没有一个解决方案是可取的。

所以答案不是以上两种。相反,如果没有真正的理由不这样做,则将全局限定为static使其在定义它的模块之外不可见,然后在同一模块中定义适当的访问函数。

即使没有静态声明,访问函数也是一个好方法,因为您可以验证参数、确保数据一致性、在必要时应用互斥,并且在调试期间您可以通过仅在访问函数中设置断点来捕获所有访问,而不是在任何地方否则可能会发生访问。

您或许应该阅读A Pox on Globals - 它指的是嵌入式系统,但同样适用于桌面应用程序。

于 2012-09-18T18:15:35.430 回答