goto ステートメントに関するすべての推奨事項に、私は少し恐怖を感じています。
goto を使用するとコードが混乱し、プログラマーのエラーが発生しやすくなることがわかりました。私の好みは、最も極端な状況を除いて、その使用を完全に避けることです. 私はほとんどそれを使用することはありません。学問的な完璧主義のせいではなく、1年以上経つと、私が提案する代替案よりも全体的な論理を思い出すのが常に難しいように見えるからです.
ものを忘れる可能性を最小限に抑えるために物事をリファクタリングするのが大好きな人 (ポインターをクリアするなど) として、最初にいくつかの関数を追加します。同じプログラムでこれらをかなり再利用する可能性が高いと思います。関数 imalloc() は、間接ポインターを使用して malloc 操作を行います。ifree() はこれを元に戻します。cifree() は条件付きでメモリを解放します。
それを踏まえて、コードの私のバージョン (デモンストレーションのために 3 番目の引数を使用) は次のようになります。
// indirect pointer malloc
int imalloc(void **mem, size_t size)
{
return (*mem = malloc(size));
}
// indirect pointer free
void ifree(void **mem)
{
if(*mem)
{
free(*mem);
*mem = NULL;
}
}
// conditional indirect pointer free
void cifree(int cond, void **mem)
{
if(!cond)
{
ifree(mem);
}
}
int func(void **mem1, void **mem2, void **mem3)
{
int result = FALSE;
*mem1 = NULL;
*mem2 = NULL;
*mem3 = NULL;
if(imalloc(mem1, SIZE))
{
if(imalloc(mem2, SIZE))
{
if(imalloc(mem3, SIZE))
{
result = TRUE;
}
cifree(result, mem2);
}
cifree(result, mem1);
}
return result;
}
最後に、関数からの戻り値を 1 つだけにすることを好みます。間に飛び出すのは速いです(そして私の意見では、ちょっと汚いです)。しかし、もっと重要なのは、関連するクリーンアップ コードを意図せずに簡単にバイパスできるようにすることです。