Wie bei allem, was auf den ersten Blick beängstigender erscheint als später, ist der beste Weg, die anfängliche Angst zu überwinden, in das Unbehagen des Unbekannten einzutauchen ! Es ist manchmal so, wie wir es am meisten lernen.
Leider gibt es Einschränkungen. Während Sie noch lernen, eine Funktion zu verwenden, sollten Sie beispielsweise nicht die Rolle eines Lehrers übernehmen. Ich lese oft Antworten von denen, die anscheinend nicht wissen, wie man sie verwendet realloc
(dh die derzeit akzeptierte Antwort! ) Und anderen sagt, wie sie falsch verwendet werden sollen, gelegentlich unter dem Deckmantel, dass sie die Fehlerbehandlung weggelassen haben , obwohl dies eine häufige Gefahr ist was erwähnt werden muss. Hier ist eine Antwort, die erklärt, wie man realloc
richtig verwendet . Beachten Sie, dass die Antwort den Rückgabewert in einer anderen Variablen speichert , um eine Fehlerprüfung durchzuführen.
Jedes Mal, wenn Sie eine Funktion aufrufen und wenn Sie ein Array verwenden, verwenden Sie einen Zeiger. Die Konvertierungen erfolgen implizit, was, wenn überhaupt, noch beängstigender sein sollte, da die Dinge, die wir nicht sehen, häufig die meisten Probleme verursachen. Zum Beispiel Speicherlecks ...
Array-Operatoren sind Zeigeroperatoren. array[x]
ist wirklich eine Abkürzung für *(array + x)
, die unterteilt werden kann in: *
und (array + x)
. Es ist sehr wahrscheinlich, dass Sie *
das verwirrt. Wir können weiterhin die Zugabe von dem Problem beseitigen , indem angenommen x
werden 0
somit, array[0]
wird , *array
da das Hinzufügen 0
nicht den Wert ändern ...
... und so können wir sehen, dass *array
das gleichbedeutend ist mit array[0]
. Sie können eines dort verwenden, wo Sie das andere verwenden möchten, und umgekehrt. Array-Operatoren sind Zeigeroperatoren.
malloc
, realloc
Nicht und Freunde erfinden das Konzept eines Zeigers , die Sie die ganze Zeit verwendet haben; Sie verwenden dies lediglich , um eine andere Funktion zu implementieren, bei der es sich um eine andere Form der Speicherdauer handelt, die am besten geeignet ist, wenn Sie drastische, dynamische Größenänderungen wünschen .
Es ist eine Schande, dass die derzeit akzeptierte Antwort auch gegen einige andere sehr fundierte Ratschläge zu StackOverflow verstößt und gleichzeitig die Gelegenheit verpasst, eine wenig bekannte Funktion einzuführen, die genau für diesen Anwendungsfall glänzt: flexibles Array Mitglieder! Das ist eigentlich eine ziemlich kaputte Antwort ... :(
Wenn Sie Ihre definieren struct
, deklarieren Sie Ihr Array am Ende der Struktur ohne Obergrenze. Beispielsweise:
struct int_list {
size_t size;
int value[];
};
Auf diese Weise können Sie Ihr Array int
in derselben Zuordnung wie Ihre zusammenfassen count
, und es kann sehr praktisch sein , sie so zu binden !
sizeof (struct int_list)
verhält sich so, als hätte value
es eine Größe von 0, sodass die Größe der Struktur mit einer leeren Liste angezeigt wird . Sie müssen noch die übergebene Größe hinzufügen, realloc
um die Größe Ihrer Liste anzugeben.
Ein weiterer praktischer Tipp ist, sich daran zu erinnern, dass dies realloc(NULL, x)
gleichbedeutend ist malloc(x)
, und wir können dies verwenden, um unseren Code zu vereinfachen. Beispielsweise:
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;
Der Grund, den ich struct int_list **
als erstes Argument gewählt habe, mag nicht sofort offensichtlich erscheinen, aber wenn Sie an das zweite Argument denken, sind Änderungen, die value
von innen vorgenommen wurden, push_back
für die Funktion, von der wir aufrufen, nicht sichtbar, oder? Das gleiche gilt für das erste Argument, und wir müssen in der Lage sein, unser array
nicht nur hier, sondern möglicherweise auch in allen anderen Funktionen, an die wir es weitergeben, zu ändern ...
array
beginnt auf nichts zu zeigen; Es ist eine leere Liste. Das Initialisieren entspricht dem Hinzufügen. Beispielsweise:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
PS Denkenfree(array);
Sie daran, wenn Sie damit fertig sind!