2

内部バッファへのポインタを返すアクセス関数を作成しています。関数のユーザーに、ポイントされているオブジェクトを更新してはならないことを示唆したいと思います。非常に不自然な例は次のとおりです。

void myAccessFunc(bool string, void* p, size_t* len)
{
  static const char* s = "aha!";
  static const int i = 123;

  if (string) {
     *(char**)p = &s;
     *len = strlen(s);
  }
  else {
     *(int**)p = &i;
     *len = sizeof(i);
  }
}

char* s;
size_t bytes;
myAccessFunc(true,&s, &bytes);
printf("Got '%s'\n", s);

はい、私はそれが薄っぺらに見えることを知っています。

私が防ぎたいのは:

char* s;
size_t bytes;
myAccessFunc(true,&s,&bytes);
s[4] = '?';

私はそれを完全に防ぐことはできないことを知っていますが、少なくともコンパイラーの警告がユーザーにそれをしてはいけないことを示唆することを望みます。彼らが私のポインターを投げた場合、それは彼らの問題です。これを行うconstとvoidおよび*の組み合わせはありますか?私は次のようなことを試しました:

void myAccessFunc(bool string, const void** p, size_t* len);

しかし、それはポインタの空白をなくしたように見えたので、発信者は次のことをしなければなりませんでした。

const void* p;
size_t bytes;
myAccessFunc(true, &p, &bytes);

また

const char* s;
size_t bytes;
myAccessFunc(true, (const void**)&s, &bytes);

できませんでした:

const int * ip;
const char* s;
size_t bytes;
myAccessFunc(true, &s, &bytes);
myAccessFunc(false, &i, &bytes);

私はついにやって来ました:

const void* myAccessFunc(bool string, size_t* len);

ユーザーが行う場合:

char* p = myAcccessFunc(true,&bytes);

コンパイラー(少なくともGCC)は、修飾子を破棄することについて文句を言います。

4

7 に答える 7

10

次のようなことをするのが最善でしょう:

const void * myAccessFunc();

内部へのポインターを返す場合、これは out パラメーターとして渡すよりも少し自然です。

これを out パラメーターとして渡す場合は、次のようにします。

void myAccessFunc(const void **p);

これにより、誤ってこれを行うことを防ぎます。

void *p;  /* error: must be 'const void *p;' */
myAccessFunc(&p);
于 2009-02-19T21:03:58.733 に答える
3

できることは 2 つあります。

  • const void* を返す
  • 戻り値を変更しないようにユーザーに伝える API のドキュメントを作成します。

そうは言っても、そのようなポインターを試してみることに決めたAPIユーザーは、得られるものに値します:P.

于 2009-02-19T21:06:35.250 に答える
2

constness を捨てることができるので、防ぐことは不可能です。関数のパラメーターを const にする場合は、関数内でキャストする必要があります。また、関数を使用している人に嘘をつき、あらゆる種類の楽しいバグを引き起こす可能性があります.

代わりにポインタを返してみることができます。そうすれば、少なくとも自分の const に違反することはありません。ただし、この場合は適切ではないかもしれません。

于 2009-02-19T21:02:17.117 に答える
2

ポインターを返すのが最善ですが、それを out パラメーターにする必要がある場合は仲介として構造体を使用できます。

typedef struct _ptr_holder {
   const void* ptr;
} ptr_holder;

void myAccessFunc( bool string, ptr_holder* ptr ) {
...
}

ptr_holder s;
myAccessFunc(true,&s);
printf("Got '%s'\n", s.ptr);

それはばかげていますが、うまくいくはずです

于 2009-02-19T21:14:44.953 に答える
1

それで、あなたが返すポインタを介しての変更を防ぎたいですか? これを試して:

const void* myAccessFunc(bool string);

これの何が問題なのですか?有効な回答に反対票を投じる場合は、コメントを残してください。

于 2009-02-19T21:06:28.917 に答える
1

内部データ構造を公開したくない C ライブラリを作成している場合は、別のルートに進み、指定されていない struct typedef を使用して実装を非表示にすることをお勧めします。これは不透明型とも呼ばれます

例:

my_interface.h

 #ifndef __MYINTERFACE_H__
 #define __MYINTERFACE_H__

 /* The unspecified struct statement */
 typedef struct s_my_data t_my_data;

 t_my_data  *new_my_data(int someInitializer);
 void        free_my_data(t_my_data *data);
 int         enter_my_data(t_my_data *data, int someDataToEnter);

 const char *return_str_my_data(t_my_data *data);

 #endif /* __MYINTERFACE_H__ */



my_interface.c

 #include <my_interface.h>

 /* Keep struct in .c file */
 struct s_my_data {
     int    length;
     char  *string;
 };

 t_my_data *new_my_data(int someInitializer)
 {
     /* the exercise */
 }

 void free_my_data(t_my_data *data)
 {
     /* the exercise */
 }

 int enter_my_data(t_my_data *data, int someDataToEnter)
 {
     /* the exercise */
 }

 const char *return_str_my_data(t_my_data *data)
 {
     /* the exercise */
 }
于 2009-02-22T23:58:18.677 に答える
0

これは C または C++ ですか? なぜ int の場合、ポインターを static const に渡すのですか? インターフェイスが疑わしい。

インターフェイスのブール値をオーバーロードして削除します。

void myAccessFunc( const char* * const p, size_t* len){
   *p = "blahblahblah";
   *len = 12;
}

void myAccessFunc( const int* * const ppI, size_t* len){
   static const int i = 123;
   *ppI = &i;
   *len = 4;
}

テストも手放します。ユーザーは元の関数の true または false を知っているため、どちらを使用するかがわかります。強いタイピングはあなたの友達です。型とポインターが一致しないエラーのクラスを取り除きます...

ところで、このような制御フラグをオーバーロードに対して渡すことは望ましくありません。特に小さなメソッドではそうです。

于 2009-04-25T23:31:40.270 に答える