c - 没有定义的不透明结构

标签 c encapsulation opaque-pointers

我正在为我的 hashmap 数据结构设计一个迭代器接口(interface)。当前的设计如下所示:

// map.h
typedef struct map_iterator map_iterator;

// map.c
struct map_iterator
{
    // Implementation details
};

// client.c
map *m = map_new();
map_iterator *it = map_iterator_new(m);
void *key, *value;
while (map_iterator_next(it, &key, &value)) {
    // Use key, value
}
map_iterator_free(it);

但是,这需要为迭代器对象分配堆,并且客户端必须记住在完成后释放迭代器。如果我让 map_iterator_new 返回堆栈上的迭代器,代码如下所示:

// map.h
typedef struct map_iterator
{
    // Implementation details
};

// client.c
map *m = map_new();
map_iterator it = map_iterator_new(m);
void *key, *value;
while (map_iterator_next(&it, &key, &value)) {
    // Use key, value
}

但是,这需要我向客户端代码提供 map_iterator 结构的定义(否则我会收到不完整的类型错误)。我想隐藏这个定义,只提供声明。

有什么办法可以实现吗?本质上,我正在寻找一种方法来告诉客户端代码“这个结构占用 X 个字节,因此您可以在堆栈上分配它,但我不会告诉您如何访问它的成员”。

编辑:请仅使用标准 C! (没有编译器扩展/平台特定的功能)

最佳答案

使用序列化。

您始终可以将 T 的对象复制到 unsigned char 数组,然后再复制回 T 类型的对象。该对象将与原始对象相同。 T 可以是任何对象类型,这可以通过自动存储持续时间(堆栈)来完成:

int value = 568;
unsigned char store[sizeof( int )];
memcpy( store , &value , sizeof( int ) );
int other;
memcpy( &other , store , sizeof( int ) );
assert( other == value ),

这可以(ab)用于对用户隐藏实现。定义两个结构,一个定义实际实现且对用户不可见,另一个可见且仅包含适当大小的 unsigned char 数组。

implementation.c

#include "implementation.h"

struct invisible
{
    int element1;
    char element2
    float element3;
    void** element4;
};

_Static_assert( sizeof( struct invisible ) <= VISIBLE_SIZE );

struct visible New( void )
{
    struct invisible i = { 1 , '2' , 3.0F , NULL };
    struct visible v = { 0 };
    memcpy( &v , &i , sizeof(i) );
    return v;
}

void Next( struct visible* v )
{
    struct invisible i = { 0 };
    memcpy( &i , &v , sizeof(i) );
    i.element1++;    //make some changes
    const int next = i.element;  
    memcpy( &v , &i , sizeof(i) );
    return next;
}

implementation.h

#define VISIBLE_SIZE 24    //make sure it greater or equal to the size of struct invisible
struct visible
{
    unsigned char[VISIBLE_SIZE];
};

struct visible New( void );
int Next( struct visible* v );

user.c

#include "implementation.h"

void Func( void )
{
    struct visible v = New();
    while( 1 )
    {
         const int next = Next( &v );
         if( next == 10 )
         {
              break;
         }
         printf( "%d\n" , next );
    }
}

此示例仅涉及成员 element1。在实际实现中,您可以自由修改不可见结构。

关于c - 没有定义的不透明结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38050401/

相关文章:

c++ - 封装:我应该将一个对象的数据传递给另一个修改它的类吗?

java - 封装 Integer.parseInt() 的好方法

c typedef(ed) 不透明指针

c - 向不透明句柄添加 const-ness

ios - '初始化()' is deprecated: init() will be removed in Swift 3. Use ` 零`

c - glibc 函数 strtoull() 失败

c - HLSL - int(x) 或 int(value) 在高级着色语言 2.0 中有何作用?

android - 封装ViewHolder功能以供重用

c - 如何将 int 和 double 作为输入而不是 char?

c - 如何将 N 个单元格从数组 1 复制到数组 2 ,并接收错误的返回值?