6

ハッシュマップ データ構造の反復子インターフェイスを設計しています。現在のデザインは次のようになります。

// 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のみでお願いします!(コンパイラ拡張/プラットフォーム固有の機能はありません)

4

3 に答える 3

2

シリアル化を使用します。

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) 使用できます。2 つの構造体を定義します。1 つは実際の実装を定義し、ユーザーには表示されません。もう 1 つは表示され、適切なサイズの unsigned char の配列のみを含みます。

実装.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;
}

実装.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 );
    }
}

この例では、 member のみに触れていelement1ます。実際の実装では、目に見えない構造体を自由に変更できます。

于 2016-06-27T14:51:07.980 に答える