2014-01-31 13 views
8

Ich muss mehrere Arrays des gleichen Typs und Form zuweisen. Am Anfang habe ich so etwas wie:Zuweisung mehrerer Arrays des gleichen Typs

void alloc_arrays_v1(size_t nmemb) 
{ 
    int *a1, *a2, *a3; 

    a1 = malloc(nmemb * sizeof int); 
    a2 = malloc(nmemb * sizeof int); 
    a3 = malloc(nmemb * sizeof int); 

    /* do some stuff with the arrays */ 

    free(a1); 
    free(a2); 
    free(a3); 
} 

zu vermeiden Um malloc und free mehrmals aufrufen, änderte ich die oben in:

void alloc_arrays_v2(size_t nmemb) 
{ 
    int *a, *a1, *a2, *a3; 

    a = malloc(3 * nmemb * sizeof int); 
    a1 = a; 
    a2 = a1 + nmemb; 
    a3 = a2 + nmemb; 

    /* do some stuff */ 

    free(a); 
} 

Dies scheint in Ordnung zu sein (in dem Sinne, dass die Funktionen Verhalten Sie sich im realen Fall genauso), aber ich frage mich, ob das immer noch C-Code ist (undefiniertes Verhalten?), und ob ich diese Methode auf komplexe Datenarten (Arrays von Strukturen usw.) erweitern kann.

+3

Sein völlig gültiger C-Code, und ja, Sie können es mit anderen Typen einschließlich Strukturen (Zeigerarithmetik funktioniert nur, wenn Sie es lassen, und Sie lassen es einfach gut). Führen Sie es in einem Debugger aus und berechnen Sie die Adressen, die mit "a" beginnen, um dies zu bestätigen. – WhozCraig

+0

@WhozCraig: Ich mache das in der realen Welt :) – michaelmeyer

+2

Nicht sicher, was das mit dem Debuggen zu tun hat, wie ich * viel * reellen Code debuggen. Aber es ist hilfreich, Schritt für Schritt Zeile für Zeile in Aktion zu sehen. Glauben Sie nicht, dass Debugger hilfreich sind, nur um Fehler zu finden; Sie sind ebenso fantastische Werkzeuge, um * gültigen * Code zu untersuchen und zu sehen, wie er auf der gewählten Plattform funktioniert. – WhozCraig

Antwort

3

Es ist in C völlig gültig. Aber denken Sie daran, nur den Zeiger a freizugeben. Ihr diese Methode ist ähnlich struct

hacken aber ich denke, ein logisches Problem in diesem Code ist, dass, wenn Sie außerhalb der Grenzen gehen für a1 oder a2 Sie nicht in der Lage sein, es zu bemerken, wie Sie gültigen Zugriff auf den Speicher wird Adressen, dh Sie erhalten keine Seg Fault.
Im ersten Fall können Sie jedoch "SegFault" erhalten und Ihren Fehler bemerken.

+0

Danke für die Präzision. Bleibt es auch für Strukturen gültig? – michaelmeyer

+0

Array-Zugriff über seinen maximalen Index hinaus ist undefiniertes Verhalten - auf dieser Grundlage ist der [struct hack ist UB] (http://stackoverflow.com/q/3711233/183120), während der OPs-Fall in keiner Weise UB ist. Speicherpools funktionieren auf diese Weise. – legends2k

+0

den letzten Satz zu beenden, oder schlimmer, Sie können * nicht * einen segfault im ersten Ausschnitt bekommen und somit * nicht * Ihren Fehler bemerken, der in vielen Meinungen (meins eingeschlossen) weit schlimmer ist als der Absturz. es ist eher ein Crash-Warten, was nie Spaß macht. In beiden Fällen solltest du vorsichtig mit den mathematischen Grenzen deines Zeigers umgehen und es wird dir gut gehen. – WhozCraig

3

Beide sind gültig, da Sie malloc verwenden, um zusammenhängenden Speicher zuzuweisen. In der Tat ähnlicher Code in der Form des zweiten Fall wird häufig verwendet, wenn Matrizen in C

Modellierung Es ist erwähnenswert, dass

int a1, a2, a3, a4; 
int* a = &a1; 
int oops = *(a + 1); 

ist undefiniertes Verhalten, da Sie nicht der Stapel Zuordnung zusammenhängend sein erwarten .

2

Es ist vollkommen gültig.

Was Sie tun, ist im Wesentlichen die gleiche wie folgt aus:

void alloc_arrays_v1(size_t nmemb) 
{ 
    typedef int one_array[nmemb]; // this is one array 
    typedef one_array three_arrays[3]; // this are three arrays 

    one_array * a; 
    int *a1, *a2, *a3; 
    a = malloc(sizeof(three_arrays)); 

    a1 = a[0]; // a[0] is a one_array, which decays into an int * here. 
    a2 = a[1]; // the same 
    a3 = a[2]; // as above 

    /* do some stuff with the arrays */ 

    free(a); 
} 

mit dem Unterschied, dass die Berechnungen hier durch Zeiger und Array-Arithmetik durchgeführt werden.

Verwandte Themen