当初よりも恐ろしいように見えるすべてのものと同様に、最初の恐怖を乗り越える最善の方法は は、未知の不快感に身浸す!結局のところ、それは私たちが最もよく学ぶような時です。
残念ながら、制限があります。関数の使い方をまだ学習している間は、たとえば教師の役割を引き受けないでください。よくある落とし穴であるにもかかわらず、エラー処理を省略していると偽って、使い方を知らないように見える人からの回答realloc
(つまり、現在受け入れられている回答!)言及する必要があります。正しく使用する方法を説明する回答です。答えは、エラーチェックを実行するために、戻り値を別の変数に格納することです。realloc
関数を呼び出すたび、および配列を使用するたびに、ポインターを使用しています。変換は暗黙的に行われています。これは、恐らくもっと恐ろしいはずです。ほとんどの問題を引き起こすのは、目に見えないものだからです。たとえば、メモリリーク...
配列演算子はポインター演算子です。array[x]
は本当にのショートカットであり*(array + x)
、次のように分解できます:*
および(array + x)
。それが*
あなたを混乱させるものである可能性が最も高いです。我々はさらに仮定して問題から付加を排除することができるx
ことが0
、したがって、array[0]
となる*array
追加ため0
値を変更しません...
...したがって、これは*array
と同等であることがわかりarray[0]
ます。どちらか一方を使いたい場所で使用でき、その逆も可能です。配列演算子はポインター演算子です。
malloc
、realloc
そして友達はあなたがずっと使ってきたポインタの概念を発明していません。これは、これを使用して他の機能を実装するだけです。これは、異なる形式のストレージ期間であり、サイズの大幅で動的な変更が必要な場合に最適です。
現在受け入れられている答えがStackOverflowに関する他の非常に根拠のあるアドバイスの粒度にも反すると同時に、このユースケースにぴったりとなるあまり知られていない機能を導入する機会を逃してしまうのは残念です:フレキシブル配列メンバー!それは実際にはかなり壊れた答えです... :(
を定義するときは、上限なしで、構造の最後でstruct
配列を宣言します。例えば:
struct int_list {
size_t size;
int value[];
};
これにより、の配列をint
と同じ割り当てに統合するcount
ことができ、このようにバインドすることは非常に便利です。
sizeof (struct int_list)
はvalue
サイズが0であるかのように動作するため、リストが空の構造体のサイズがわかります。realloc
リストのサイズを指定するには、渡されたサイズに追加する必要があります。
もう1つの便利なヒントは、とrealloc(NULL, x)
同等であることを覚えておくことmalloc(x)
です。これを使用してコードを簡略化できます。例えば:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
struct int_list **
最初の引数として使用することを選択した理由はすぐには明らかではないように思われるかもしれませんが、2番目の引数について考えるとvalue
、内部から行われた変更は、push_back
呼び出し元の関数からは見えません。同じことが最初の引数にも当てはまりますarray
。ここだけでなく、他の関数でもを変更できるようにする必要があります...
array
何も指さないところから始まります。空のリストです。それを初期化することは、それに追加することと同じです。例えば:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
PS それが終わったら忘れないでくださいfree(array);
!