次の 2 つの関数を考えてみましょう。
int add1(int x,int y)
{
return x+y;
}
void add2(int x,int y,int *sum)
{
*sum=x+y;
}
通常は add1 形式の関数を使用しますが、add2 形式の関数を使用するコードをいくつか見つけました。
サイズの戻り値が大きい場合でも (配列や構造体のように)、そのポンター
を返すことができます。2 番目の形式を使用する理由があるのだろうか?
成功状態を返す理由もあります。
次のような関数がたくさんあります。
bool f(int arg1, int arg2, int *ret)
{
}
bool
(または)関数enum
の成功を返します。チェックする代わりにif ret is null...
(そして、複数の変数がある場合)。
関数から 2 つの値を返したい場合、関数 add2 のようにポインターを使用しない限り、C は無力です。
void add2()
{
/* Some Code */
*ptr1=Something;
*ptr2=Something;
}
フォーム 2 は、C の「複数のリターン」で非常に一般的です。標準的な例は、バッファーへのアドレスとバッファーの長さを返すことです。
/* Returns a buffer based on param. Returns -1 on failure, or 0 on success.
Buffer is returned in buf and buflen. */
int get_buffer(void *param, char **buf, int *buflen);
返されるオブジェクトが大きい場合、または関数の戻り値が他の目的 (エラー状態の通知など) に使用される場合、ポインターを介して渡されたメモリに書き込むことによって値を返すことは合理的です。あなたが示したコードでは、これら2つのどちらにも当てはまらないので、最初の実装に行きます.
関数からポインタを返すときは、ポインタが指すメモリが関数呼び出し後に有効であることを確認する必要があります。つまり、ポインターはヒープを指している必要があり、ヒープへの割り当てが必要になります。これは発信者に負担をかけます。明示的に割り当てていないメモリの割り当てを解除する必要があります。
のような小さなものを使用している場合、フォーム 2 の関数はフォーム 1 の関数よりも高速ではありませんint
。実際、この場合、渡されたポインターを逆参照する必要があるため、2 番目の方法は遅くなります。この場合、目的が値の配列を渡すことである場合にのみ役立ちます)
非常に大きなデータを関数に渡す場合を除き、常に形式 1 の関数を使用してください。その場合、フォーム 2 の方が高速です。
2 番目の形式を使用する理由は、大きなオブジェクトの場合、コピーを避けたいからです。それらをコピーする代わりに、それらのメモリ アドレスを関数に渡すことができます。これがポインタの出番です。したがって、関数にすべてのデータを渡す代わりに、このデータの場所を指定するだけです。(この類推で十分だと思います)
それは主に好みと地域の慣習の問題です。2 番目の形式は、それぞれの 3 番目のパラメーターが常に戻り値へのポインターとして渡される他の同様の関数の束と一緒に使用される場合があります。
個人的には、ほぼすべての目的で最初の形式が好きです。これは、ポインターを渡す必要がなく、戻り値を処理する際にある程度の型の柔軟性が得られます。