質問
私はログラム:グローバルサーベイとアクセス機能を返すポインタを内部バッファていただきたいと思いますようにヒントをユーザーの私であるという機能だけを更新できるオブジェクトの指摘。非常にしたり、逆に例することはできない。
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);
そうでしょうflakey.
何をしたいの防止には:
char* s;
size_t bytes;
myAccessFunc(true,&s,&bytes);
s[4] = '?';
思いを完全に防止で今以上のようにコンパイラの警告をヒントになっているユーザーすべきではないとのこと。れば、キャストは私のポインタ、それはそれを問題です。いくつかの組み合わせconstと無効*そのまるのか?てみましたようなもの:
void myAccessFunc(bool string, const void** p, size_t* len);
だったのですかvoidnessのポインタで呼び出しなければいけなかった:
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、少なくともなに不満をもってい捨てに行う予定です
解決
これは、ような何かをするのがベストだろう
const void * myAccessFunc();
あなたが内部へのポインタを返す場合は、、これはもう少し自然outパラメータとして渡すよります。
あなたが出て、それをパラメータとして渡すとしたら、あなたが望むます:
void myAccessFunc(const void **p);
誤ってこれをやってからそれらを防止する。
void *p; /* error: must be 'const void *p;' */
myAccessFunc(&p);
他のヒント
いうことができるの?
- 返const void*
- 書き込む文書をごAPI語のいないユーザへの変更は返される値
ということは、APIリストのユーザーを決定しmuckとポインタのようにふっくP.
の防止あなたはconst性を離れてキャストすることができるので、不可能です。あなたの関数パラメータのconstを作る場合は、関数内で自分でそれを離れてキャストする必要があります。また、あなたの関数を使用して、誰に嘘をついているはずだと楽しいバグのすべての種類を引き起こす可能性があります。
あなたは代わりにポインタを返す試みることができます。そして、あなたは、少なくともあなた自身のconstに違反することはないと思います。それは、しかし、この場合には適切でない可能性があります。
のポインタを返すことがベストですが、あなたはを場合は、絶対には、仲介者としての構造体を使用することができ、それを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);
それは陳腐だが、それはトリックを行う必要があります。
だからあなたはあなたが返すポインタを経由しての変更を防止したいですか?これを試してください:
const void* myAccessFunc(bool string);
の本の何が問題になっているのですか?あなたは、有効な答えを否決しようとしている場合は、コメントを残してください。の
余分なのルートのを移動して、不特定の構造体の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 */
}
このCまたはC ++ですか? なぜint型の場合には、あなたは静的定数へのポインタを渡していますか? インタフェースは疑わしいです。
過負荷およびインタフェースにブールを取り除くます:
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;
}
あまりにもテストを取り除きます。ユーザーは、元の関数のための真または偽の知っているので、彼は1つが使用するかを知っています。強い型付けはあなたの友達です。タイプとポインタが矛盾しているエラーのクラスを取り除く...
ところで過負荷に対するそのような制御フラグを渡すことは、特に小さな方法でので、望ましくない。