我正在为我的 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/