![]() ![]() ![]() | Pointers og Arrays |
Variable kræver lagerplads når programmet kører. Vi siger, at der allokeres lager til vore vore variable. Når vi i kildeprogrammet har erklæret en variabel vil køretidssystemet klare lagerallokeringen af variablen uden yderligere programøranstrengelser. Dette er statisk lagerallokering.
I C er det også muligt, når programmet kører, at bede om lager, som ikke er indeholdt i nogen variable. Når dette sker vil vi få overdraget en pointer til begyndelsen af det pågældende lagerområde. Dette kaldes dynamisk lagerallokering.
|
26.1. Statisk lagerallokering
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I kurset indtil nu har vi benyttet statisk lagerallokering for alle data |
|
I programmet herunder allokeres tab1 og tab2 statisk i main. Til tab1 afsættes plads til N doubles. N er en symbolsk konstant, som er defineret til 500. Til tab2 afsættes plads til N*K doubles, altså konkret 500 doubles (eller typisk 4000 bytes). Der allokeres naturligvis også lager til i.
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #define N 500 #define K 10 int main(void) { int i; double tab1[N]; /* allocation of N doubles */ double tab2[N*K]; /* allocation of N*K doubles */ /* do something with tab1 and tab2 */ return 0; } | |||
|
Når main er kørt færdig frigives lagerpladsen, som er afsat til tab1, tab2 og i.
Statisk lagerallokering er knyttet til erklæringen af variable. Udtryk som indgår i indeksgrænser for et array skal være statiske udtryk |
26.2. Dynamisk lagerallokering (1)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I mange tilfælde ved vi først på programmets køretid hvor meget lager vi har brug for. Dette kan f.eks. afhænge af et tal, som er indlæst tidligere i programkørslen. Derfor er dynamisk lagerallokering ikke let at komme uden om.
Der er ofte behov for en mere fleksibel og dynamisk form for lagerallokering, hvor det kørende program eksplicit
allokerer lager.
|
|
I program 26.2 vises et forsøg på at at allokere passende plads til a i forhold til n, som er et indlæst heltal.
Ideen med at indlæse n i en ydre blok i forhold til den blok, hvor arrayet allokeres er god. Men vi skal ikke regne med, at den virker i C. ANSI C kræver, at n er et konstant udtryk, hvilket vil sige at der kun må indgå konstanter i udtrykket. sizeof operatoren kan også indgå.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h> int main(void) { int n; printf("Enter an integer size:\n"); scanf("%d",&n); { int i; double a[n]; for (i = 1; i < n; i++) a[i] = (double)i; for (i = 1; i < n; i++) printf("%f ", a[i]); printf("\n"); } return 0; } | |||
|
I stedet for at bruge ideen i program 26.2 skal vi anvende enten malloc eller calloc, som eksemplificeret i program 26.3. På det røde sted allokerer vi plads til n heltal (ints). Vi får en pointer til lagerområdet. Læg mærke til at a er en pointer til en int. Det nyallokerede lagerområde bruges i de to efterfølgende forløkker. På det blå sted deallokerer vi igen lagerområdet. Det betyder at vi overgiver lageret til C køretidssystemet, som så efterfølgende kan bruge det til andre formål. F.eks. kan lageret genbruges hvis vi lidt efter igen beder om nyt lager via calloc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h> #include <stdlib.h> int main(void) { int *a, i, n, sum = 0; printf("\n%s", "An array will be created dynamically.\n\n" "Input an array size n followed by n integers: "); scanf("%d", &n); a = calloc(n, sizeof(int)); /* get space for n ints */ for (i = 0; i < n; ++i) scanf("%d", &a[i]); for (i = 0; i < n; ++i) sum += a[i]; free(a); /* free the space */ printf("\n%s%7d\n%s%7d\n\n", " Number of elements:", n, "Sum of the elements:", sum); return 0; } | |||
|
Vi viser afslutningsvis et program, som dynamisk allokerer plads til det array, som vi illustrerede i figur 25.1. Allokeringen sker på det røde sted. I dette eksempel frigiver vi ikke lagerpladsen, idet lageret bruges helt til programafslutningen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h> #include <stdlib.h> #define N 2 #define M 3 int main(void) { int *pint, i, j; pint = malloc(N*M*sizeof(int)); for (i=0; i<N; i++) for (j=0; j<M; j++) *(pint + M*i + j) = (i+1) * (j+1); for (i = 0; i < M * N; i++){ printf("%4i ", *(pint + i)); if ((i+1) % M == 0) printf("\n"); } return 0; } | |||
|
26.3. Dynamisk lagerallokering (2)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Herunder opsummerer vi dynamisk lagerallokering.
|
I mange moderne sprog styres lager deallokering af en garbage collector, som frigiver lagerplads,
når det ikke længere kan tilgås af programmet. |
Understøttelse af lageradministration med en garbage collector er et meget spændende emne. En diskussion af dette falder dog uden for rammerne af disse noter.