为本地声明制作一个 typedef struct public,但将结构成员访问权限保留给它在其中定义的模块

Making a typedef struct public for local declaration, but keep the structure member access private to the module it is defined in

我有这样一种情况,我希望能够在其他模块中本地声明一个结构,但我只希望定义该结构的模块能够实际访问成员.请注意,这是针对嵌入式应用程序的,因此我无法动态分配内存 (malloc)。

foo.h

typedef struct my_struct T_my_struct;

int GetA(T_my_struct *bar);
int GetB(T_my_struct *bar);

foo.c

#include "foo.h"

struct my_struct
{
    int a;
    char b;
}

int GetA(T_my_struct *bar)
{
    return bar->a;
}

int GetB(T_my_struct *bar)
{
    return bar->b;
}

void Init(T_my_struct *bar)
{
    bar->a = 5;
    bar->b = 3;
}

bar.c:

#include "bar.h"
#include "foo.h"
#include <stdio.h>
#include <stdlib.h>

static T_my_struct local_instance;  // <--storage size of local_instance not know here

int main()
{
    Init(&local_instance);

    printf("A: %d\n", GetA(&local_instance));
}

我知道我可以创建一个本地 T_my_struct 指针并在 foo.c 中分配它,除非我没有如前所述的 malloc。我还意识到我可以在 foo.h 中进行结构定义;但是,我不希望其他模块(即 bar.c)直接访问任何成员。有没有一种方法可以在没有动态内存分配的情况下在 C 中执行此操作?

一种方法是将函数添加到 foo.h:

T_my_struct *get_bar_instance(void);

其在 foo.c 中的实现是:

T_my_struct *get_bar_instance(void)
{
     static T_my_struct x;
     return &x;
}

然后在 bar.c 中写 get_bar_instance() 而不是 &local_instance

如果多个文件需要一个实例,则为每个文件创建一个函数(或者您可以使用带有整数参数的单个函数)。

为了详细说明我对 Matt 的回答(或您对它的回答)的评论,此解决方案使用隐藏的资源池并处理而不是指针。

foo.h

typedef int bar_handle_t ;

int getBarHandle() ;
void freeBarHandle( bar_handle_t handle ) ;
int getA( bar_handle_t handle ) ;
int getB( bar_handle_t handle ) ;

foo.c

#include <stdbool.h>
#include "foo.h"

typedef struct
{
    int a;
    char b;
} bar_t ;

typedef struct
{
    bool in_use ;
    bar_t bar ;
} bar_pool_t ;

#define HANDLE_COUNT 20
static bar_pool_t bar_pool[HANDLE_COUNT] ;

bar_handle_t getBarHandle()
{
    bar_handle_t handle ;

    for( handle = 0 ;
         bar_pool[handle].in_use && handle < HANDLE_COUNT; 
         handle++ )
    {
        // do nothing
    }

    if( handle < HANDLE_COUNT )
    {
        bar_pool[handle].in_use = true ;
        bar_pool[handle].bar.a = 5;
        bar_pool[handle].bar.a = 3;
    }
    else
    {
        handle = -1 ;
    }

    return handle ;
} 

void freeBarHandle( bar_handle_t handle )
{
    if( handle >= 0 && handle < HANDLE_COUNT )
    {
        bar_pool[handle].in_use = false ;
    }
}

int getA( bar_handle_t handle )
{
    return bar_pool[handle].bar.a ;
}

int getB( bar_handle_t handle )
{
    return bar_pool[handle].bar.b ;
}