如何在不暴露其类型的情况下暴露 C 结构体大小?

jac*_*hab 5 c

我有以下 C 语言(不是 C++!):

module.c
    struct Private {...};
    void foo(void* private, int param) {...}

module.h
    #define PRIVATE_SIZE ???;
    void foo(void* private, int param);

main.c
    char m1[PRIVATE_SIZE];
    char m2[PRIVATE_SIZE];

    int main()
    {
        foo(m1, 10);
        foo(m2, 20);
    }
Run Code Online (Sandbox Code Playgroud)

如何在编译时公开 sizeof(Private) 以便应用程序可以静态分配其存储而不公开 Private 类型?

请注意,这是一个非常有限的嵌入式系统,动态分配不可用。

Lun*_*din 4

您不应该向调用者公开结构的大小,因为这首先破坏了私有封装的整个目的。您的私人数据的分配与调用者无关。另外,避免使用,void*因为它们完全缺乏类型安全性。

这是用 C 语言编写私有封装的方式:

  • 在 module.h 中,向前声明一个不完整类型typedef struct module module;
  • 在 module.c 中,放置该结构体的结构体定义。它仅对 module.c 可见,而对调用者不可见。这称为不透明类型
  • 调用者只能分配指向该结构的指针,而不能分配对象。
  • 调用者代码可能如下所示:

    #include "module.h"
    ...
    module* m;
    result = module_init(&m)
    
    Run Code Online (Sandbox Code Playgroud)
  • module_init函数充当“构造函数”,在 module.h 中声明并在 module.c 中定义:

    bool module_init (module** obj)
    {
      module* m = malloc(sizeof *m);
      ...
      m->something = ...; // init private variables if applicable
    
      *obj = m;
      return true;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果调用者确实需要知道对象的大小,则仅用于硬复制等目的。如果需要,请提供一个封装分配和复制的复制函数(“复制构造函数”),例如例子:

    result module_copy (module** dst, const module* src);
    
    Run Code Online (Sandbox Code Playgroud)

编辑:

请注意,分配方式是一个单独的问题。对于上述设计,您不必使用动态分配。例如,在嵌入式系统中,通常使用静态内存池。请参阅不透明数据类型的静态分配