他の人は malloc(0)
と答えました 動作します。あなたが尋ねた、まだ答えられていない質問の1つに答えます(と思います)。質問は realloc(malloc(0), 0)
についてです :
malloc(0)
とは 戻る? realloc(malloc(0),0)
の答えは同じでしょうか? ?
標準は realloc(ptr, size)
についてこう言っています :
- if
ptr
NULL
です 、malloc(size)
のように動作します 、 - それ以外 (
ptr
NULL
ではありません )、ptr
までに古いオブジェクト ポインターの割り当てを解除します。 新しく割り当てられたバッファへのポインタを返します。size
の場合 が 0 の場合、C89 は効果がfree(ptr)
と同等であると述べています。 .興味深いことに、C99 ドラフト (n1256 または n1336) でそのステートメントを見つけることができません。 C89 では、その場合に返される適切な値はNULL
だけです。 .
したがって、2 つのケースがあります:
malloc(0)
NULL
を返します 実装について。次に、あなたのrealloc()
呼び出しはrealloc(NULL, 0)
と同等です .これはmalloc(0)
に相当します 上から (そしてそれはNULL
この場合)malloc(0)
NULL
以外を返します .次に、呼び出しはfree(malloc(0))
と同等です .この場合、malloc(0)
とrealloc(malloc(0), 0)
ではない
ここで興味深いケースがあることに注意してください:2 番目のケースでは、malloc(0)
の場合です。 NULL
以外を返します 成功した場合でも、NULL
を返すことがあります。 失敗を示します。これは次のような呼び出しになります:realloc(NULL, 0)
、これは malloc(0)
と同等です NULL
を返す場合と返さない場合があります .
C99 での省略が見落としなのか、それとも C99 で realloc(ptr, 0)
という意味なのかはわかりません。 NULL
以外の場合 ptr
free(ptr)
と同等ではありません . gcc -std=c99
でこれを試しました 、および上記は free(ptr)
と同等です .
編集 :私はあなたの混乱が何であるかを理解していると思います:
コード例のスニペットを見てみましょう:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
上記は malloc(0) == realloc(malloc(0), 1024)
と同じではありません . 2 番目の malloc()
呼び出しは 2 回行われますが、最初の呼び出しでは、以前に割り当てられたポインターを realloc()
に渡しています。 .
最初のコードを最初に分析しましょう。 malloc(0)
と仮定すると NULL
を返さない 成功時、ptr
有効な値があります。 realloc(ptr, 1024)
を実行すると 、 realloc()
基本的に、サイズが 1024 で ptr
の新しいバッファが提供されます。 無効になります。適合する実装は、既に ptr
にあるものと同じアドレスを返す場合があります .だから、あなたの if
条件は true を返す場合があります。 (ただし、ptr
の値を見てください。 realloc(ptr, 1024)
の後 未定義の動作である可能性があります。)
今あなたが尋ねる質問:malloc(0) == realloc(malloc(0), 1024)
.この場合、両方の malloc(0)
LHS と RHS では NULL
以外を返します .次に、それらは異なることが保証されます。また、malloc()
からの戻り値 LHS は free()
ではありません d まだ、その他の malloc()
、 calloc()
、または realloc()
その値を返さない場合があります。つまり、条件を次のように記述した場合:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
possible
は表示されません 出力 (malloc()
の両方を除く) および realloc()
失敗して NULL
を返します ).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
OS X では、コードを実行しても何も出力されませんでした。 Linux では、possible, OK
を出力します。 .
malloc(0)
実装が定義されています C99に関する限り。
C99 から [セクション 7.20.3]
<ブロック引用>calloc、malloc、および realloc 関数の連続呼び出しによって割り当てられるストレージの順序と連続性は規定されていません .割り当てが成功した場合に返されるポインターは、任意の型のオブジェクトへのポインターに割り当てられるように適切に配置され、割り当てられた空間内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用されます (空間が明示的に割り当て解除されるまで)。割り当てられたオブジェクトの有効期間は、割り当てから解放までです。そのような各割り当ては、他のオブジェクトから切り離されたオブジェクトへのポインタを生成します。返されるポインターは、割り当てられたスペースの開始 (最下位バイトアドレス) を指します。スペースを割り当てることができない場合は、ヌル ポインターが返されます。 要求されたスペースのサイズがゼロの場合、動作は実装定義です :null ポインターが返されるか、返されたポインターがオブジェクトへのアクセスに使用されないことを除いて、サイズがゼロ以外の値であるかのように動作します。
C89 では、malloc(0) は実装依存です。C99 でこれが修正されたかどうかはわかりません。 C++ では、以下を使用:
char * p = new char[0];
明確に定義されています-有効な非nullポインターを取得します。もちろん、ポインターを使用して、未定義の動作を呼び出さずにポインターが指すものにアクセスすることはできません。
これが存在する理由については、一部のアルゴリズムにとって便利であり、ゼロ値のテストでコードを散らかす必要がないことを意味します。