次の場合に最適なソリューションは何ですか:
- 私たちの API はユーザーに構造を返します
- ユーザーがその内容を読めるようにしたい
- 他の API 関数に渡される可能性があり、その内容は正しいはずなので、ユーザーに変更してほしくありませんか?
関数は、const 構造体へのポインターを返すことができます。それで:
さらに先に進むには、構造体の不完全な宣言のみを呼び出し元に提供することができます。これは、その名前のみを明らかにし ( のようにstruct foo;
)、その内容を定義しません ( のようにstruct foo { int x;… };
)。呼び出し元が構造体の不完全な宣言しか持っていない場合、呼び出し元は構造体へのポインターを受け取り、それを格納して引数として渡すことができますが、それを使用して構造体にアクセスすることはできません (変換などの異常な手段による場合を除きます)。別の型へのポインターに、または構造体の独自の定義を提供することによって)。
呼び出し元が構造体の不完全な宣言しか持たないが、構造体の内容を使用できる必要がある場合は、構造体へのポインターをパラメーターとして受け取り、構造体内から情報を返す追加の関数を提供する必要があります。
ユーザーが構造体の内容にアクセスするのを止める方法はありません。これが必要な場合は、不透明な値を返し、API を追加してこれらの不透明な値の 1 つを取得し、そこから個々の値を返す必要があります。
この関数を使用するたびに、この構造体のコピーを作成し、コピーを使用して返すことができると思います。
このように、関数が呼び出されるたびに、新しいコピーが作成されます。
また、ユーザーmalloc
にメモリを与えて API にアドレスを与えることができます。API はアドレスmemset
を埋めるために使用するだけなので、ユーザーはデータの使用が終了した後にメモリを解放できます。
またopaque pointer
、構造体をどこにでも保存したくない場合は、 a を使用できます。
PS:コマンドで3番目の提案を言うと、反対票を獲得しますが、他の人がこれを彼の答えに追加して賛成票を獲得するのを見ますが、最初にこの行がありません。
ここでの回答を拡張するには、 opaque の使用を示唆していますstruct
。
C では、ユーザーがデータにアクセスするのを防ぐ方法はほとんどありません。パブリック API のパラメーターと戻り値として処理する場合、データを非表示にしたり、ユーザーがそのデータにアクセスしないように契約で義務付けstructs
たりする方法がいくつかあります。
おそらく opaque の最も明白な一般的な使用法struct
は<stdio.h>
FILE *
. 標準ライブラリを使用してファイルの読み取り/書き込み/クエリを実行するときはいつでもstruct FILE *
、fwrite
. 構造を調べると、プラットフォーム間で同じ実装であることが保証されていないため、未定義の動作が発生します。
ユーザーが一部のデータを変更できるようにして、他のデータを変更できないようにする場合は、次のようにします。
typedef struct
{
void * _my_private_data; //KEEP OUT
char * name;
int count;
//etc
}my_api_type;
次に、ユーザーに公開されるすべての関数呼び出しの最初のパラメーターを定義して、それらのいずれかを取ることができますstructs
。
my_api_type set_internal_flag(my_api_type * obj, int flag);
プライベート データが隠されていることを確認すると、API 関数の背後にある構造体をどのように定義するかに関係なく、void *
仕様が変更されても互換性が維持され、何かが更新されたときにユーザーがコードを変更する必要がないことを実装で保証できます。