Array initialisieren mit funktionswert, malloc oder [size]?
-
Hi, ich mache seit einiger Zeit mal wieder etwas in C. Mein Wissen ist bisschen eingestaubt und wollte lieber nochmal nachfragen.
Wenn ich eine Funktion habe z.B:
void foo( int size)und darin eine array mit der Größe size initialisieren möchte, kann ich ja:
int *arr = malloc( sizeof(int) * size)
machen.
Testweise habe ich auch mal:
int arr[size]
gemacht.Der Compiler hat es zu meiner Verwunderung akzeptiert. Ich dachte "name[size]" geht nur, wenn size schon bei compilezeit explizit vorgegeben ist, also z.B.:
int arr[42]
oder
int size = 52
int arr[size]Warum geht das auch, wenn es eine unbekannte Zahl beim Funktionsaufruf bekommt?
sollte man in dem Fall lieber malloc oder [] nutzen?
wenn ich [], brauch man kein free(arr) am Ende der Funktion, jedoch bei malloc, richtig?
-
Das mit dem
[size]
ist C99. Nennst sich variable length Array (VLA). Das ist ein leider viel missbrauchtes Feature (oftmals versehentlich, weil die Leute gar nicht richtig C können und gar nicht wissen, dass es nicht gehen sollte), dass dann auch prompt im nächsten Standard zu einem optionalen Feature heruntergestuft wurde.Im allgemeinen solltest du malloc benutzen, wenn du die Größe eines Arrays gar nicht kennst. Wenn du ganz sicher weißt, dass die Größe maximal nicht sehr groß werden kann, dann kannst du auch ein VLA benutzen. In der Regel wirst du das nicht wissen und das ist auch der häufigste Fall, wo VLAs falsch eingesetzt werden.
Um noch zu zeigen, wie man VLAs richtig benutzt:
Wirklich glänzen tun VLAs im Zusammenspiel mit mehrdimensionalen Arrays. Entweder als Funktionsparameter:void foo(int x, int y, double data[x][y])
oder im Zusammenspiel mit malloc:
double (*data)[x] = malloc(x*y*sizeof(double))
Die funktionieren wie erwartet. Das heißt, man kann dann das Array wie
data[3][4];
ansprechen und es wird automatisch der korrekte Index berechnet; man muss nicht mehr selber rechnen.
-
Danke für die Antwort.
size wird höchstwahrscheinlich in dem Bereich 100 bis 100.000 liegen. Das würde ich mal als groß einstufen.
Das array wird nur innererhalb der Funktion erstellt. Es ist nur ein 1-D array.
D.h. auch wenn man VLAs "richtig benutzt" sollte man das nur bei kleine Größe machen?Sicher, dass in dem Beispiel der Fakotr x auf der rechten seite mit drin ist?
double (*data)[x] = malloc(x*y*sizeof(double))
intuitiv für ein data[x][y] array würde ich eher so denken:
double (*data)[x] = malloc(y*sizeof(double))
sollte man das auch nur dann machen, wenn man weiß, dass x nicht groß wird?
und wann/wie müsste ich da free() verwenden?
-
Gast42 schrieb:
Sicher, dass in dem Beispiel der Fakotr x auf der rechten seite mit drin ist?
Ja.
double (*data)[x] = malloc(x*y*sizeof(double))
intuitiv für ein data[x][y] array würde ich eher so denken:
double (*data)[x] = malloc(y*sizeof(double))
Wie viele doubles enthält ein Feld von x*y doubles?
sollte man das auch nur dann machen, wenn man weiß, dass x nicht groß wird?
Nein, die Größe ist dann egal.
und wann/wie müsste ich da free() verwenden?
So wie sonst auch, zu jedem malloc genau ein free auf den Zeiger. Also
free(data)
. Das VLA existiert hier gar nichts, es stellt nur den Datentyp auf den der Zeiger zeigt. Es wird nirgends ein VLA erstellt, es wird bloß ein großer Block Speicher gemalloct, der dann wie ein VLA benutzt wird, damit man sich händische Indexberechnungen spart.
-
Ich dachte, er macht das dann für jedes x.
Alternativ gäng dann auch:double (*data)[x] = malloc(y*sizeof(*data))
Habe es aber nochmal überdacht und es macht so, wie es richtig ist mehr Sinn.
Danke
-
Gast42 schrieb:
Ich dachte, er macht das dann für jedes x.
Abgesehen davon, dass da keine Schleife ist und in C sowieso so gut wie nichts automatisch geschieht:
double (*data)[x]
Das heißt nicht etwa, dass data ein Array von double-Zeigern wäre, sondern dass data ein Zeiger auf ein double-Array sein soll. Nur damit das wirklich klar ist.
-
Gast42 schrieb:
Alternativ gäng dann auch:
gäng?