Δυναμική κατανομή μνήμης σε C χρησιμοποιώντας συναρτήσεις malloc(), calloc().
Πριν μάθετε την εκχώρηση δυναμικής μνήμης C, ας καταλάβουμε:
Πώς λειτουργεί η Διαχείριση μνήμης στο C;
Όταν δηλώνετε μια μεταβλητή χρησιμοποιώντας έναν βασικό τύπο δεδομένων, ο μεταγλωττιστής C εκχωρεί αυτόματα χώρο στη μνήμη για τη μεταβλητή σε μια δεξαμενή μνήμης που ονομάζεται σωρός.
Για παράδειγμα, μια μεταβλητή float παίρνει συνήθως 4 byte (σύμφωνα με την πλατφόρμα) όταν δηλώνεται. Μπορούμε να επαληθεύσουμε αυτές τις πληροφορίες χρησιμοποιώντας το μέγεθος του χειριστή όπως φαίνεται στο παρακάτω παράδειγμα
#include <stdio.h> int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}
Η έξοδος θα είναι:
The size of float is 4 bytes
Επίσης, ένας πίνακας με καθορισμένο μέγεθος εκχωρείται σε συνεχόμενα μπλοκ μνήμης, κάθε μπλοκ έχει το μέγεθος για ένα στοιχείο:
#include <stdio.h> int main() { float arr[10]; printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}
Το αποτέλεσμα είναι:
The size of the float array with 10 element is 40
Όπως μάθαμε μέχρι τώρα, κατά τη δήλωση ενός βασικού τύπου δεδομένων ή ενός πίνακα, η διαχείριση της μνήμης γίνεται αυτόματα. Ωστόσο, υπάρχει μια διαδικασία για την εκχώρηση μνήμης στο C που θα σας επιτρέψει να εφαρμόσετε ένα πρόγραμμα στο οποίο το μέγεθος του πίνακα δεν έχει αποφασιστεί μέχρι να εκτελέσετε το πρόγραμμά σας (χρόνος εκτέλεσης). Αυτή η διαδικασία ονομάζεται "Δυναμική εκχώρηση μνήμης. "
Δυναμική εκχώρηση μνήμης σε C
Δυναμική κατανομή μνήμης είναι χειροκίνητη εκχώρηση και απελευθέρωση μνήμης σύμφωνα με τις προγραμματιστικές σας ανάγκες. Η διαχείριση της δυναμικής μνήμης γίνεται και εξυπηρετείται με δείκτες που δείχνουν στον πρόσφατα εκχωρημένο χώρο μνήμης σε μια περιοχή που ονομάζουμε σωρό.
Τώρα μπορείτε να δημιουργήσετε και να καταστρέψετε μια σειρά στοιχείων δυναμικά κατά το χρόνο εκτέλεσης χωρίς κανένα πρόβλημα. Συνοψίζοντας, η αυτόματη διαχείριση μνήμης χρησιμοποιεί τη στοίβα και η C Dynamic Memory Allocation χρησιμοποιεί το σωρό.
ο Η βιβλιοθήκη έχει λειτουργίες υπεύθυνες για τη διαχείριση δυναμικής μνήμης.
Λειτουργία | Σκοπός |
---|---|
malloc () | Εκχωρεί τη μνήμη του ζητούμενου μεγέθους και επιστρέφει τον δείκτη στο πρώτο byte του κατανεμημένο χώρο. |
calloc() | Εκχωρεί χώρο για στοιχεία ενός πίνακα. Αρχικοποιεί τα στοιχεία στο μηδέν και επιστρέφει έναν δείκτη στη μνήμη. |
realloc() | Χρησιμοποιείται για την τροποποίηση του μεγέθους του προηγουμένως εκχωρημένου χώρου μνήμης. |
Ελεύθερος() | Απελευθερώνει ή αδειάζει τον προηγουμένως εκχωρημένο χώρο μνήμης. |
Ας συζητήσουμε τις παραπάνω λειτουργίες με την εφαρμογή τους
συνάρτηση malloc() στο C
Η συνάρτηση C malloc() σημαίνει εκχώρηση μνήμης. Είναι μια συνάρτηση που χρησιμοποιείται για την δυναμική κατανομή ενός μπλοκ μνήμης. Διατηρεί χώρο μνήμης καθορισμένου μεγέθους και επιστρέφει τον μηδενικό δείκτη που δείχνει στη θέση μνήμης. Ο δείκτης που επιστρέφεται είναι συνήθως τύπου void. Σημαίνει ότι μπορούμε να αντιστοιχίσουμε τη συνάρτηση C malloc() σε οποιονδήποτε δείκτη.
Σύνταξη της συνάρτησης malloc():
ptr = (cast_type *) malloc (byte_size);
Εδώ,
- Το ptr είναι δείκτης cast_type.
- Η συνάρτηση C malloc() επιστρέφει έναν δείκτη στην εκχωρημένη μνήμη του byte_size.
Παράδειγμα malloc():
Example: ptr = (int *) malloc (50)
Όταν αυτή η δήλωση εκτελεστεί με επιτυχία, δεσμεύεται ένας χώρος μνήμης 50 byte. Η διεύθυνση του πρώτου byte του δεσμευμένου χώρου εκχωρείται στον δείκτη ptr του τύπου int.
Εξετάστε ένα άλλο παράδειγμα:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
Παραγωγή:
Value of the 6th integer is 480
- Σημειώσε ότι sizeof(*ptr) χρησιμοποιήθηκε αντί για sizeof(int) προκειμένου να γίνει ο κώδικας πιο ισχυρός όταν η δήλωση *ptr μεταδίδεται αργότερα σε διαφορετικό τύπο δεδομένων.
- Η εκχώρηση ενδέχεται να αποτύχει εάν η μνήμη δεν είναι επαρκής. Σε αυτήν την περίπτωση, επιστρέφει έναν δείκτη NULL. Επομένως, θα πρέπει να συμπεριλάβετε κώδικα για να ελέγξετε εάν υπάρχει δείκτης NULL.
- Λάβετε υπόψη ότι η εκχωρημένη μνήμη είναι συνεχόμενη και μπορεί να αντιμετωπιστεί ως πίνακας. Μπορούμε να χρησιμοποιήσουμε την αριθμητική του δείκτη για πρόσβαση στα στοιχεία του πίνακα αντί να χρησιμοποιήσουμε αγκύλες [ ]. Σας συμβουλεύουμε να χρησιμοποιείτε το + για να αναφερθείτε σε στοιχεία πίνακα, επειδή η χρήση της αύξησης ++ ή += αλλάζει τη διεύθυνση που είναι αποθηκευμένη από το δείκτης.
Η συνάρτηση Malloc() μπορεί επίσης να χρησιμοποιηθεί με τον τύπο δεδομένων χαρακτήρων καθώς και με πολύπλοκους τύπους δεδομένων όπως δομές.
free() συνάρτηση στο C
Η μνήμη για μεταβλητές κατανέμεται αυτόματα κατά το χρόνο μεταγλώττισης. Στη δυναμική εκχώρηση μνήμης, πρέπει να κατανείμετε ρητά τη μνήμη. Εάν δεν το κάνετε, ενδέχεται να αντιμετωπίσετε σφάλμα έλλειψης μνήμης.
Το δωρεάν() Η λειτουργία καλείται να απελευθερώσει/αποκατανείμει μνήμη σε C. Απελευθερώνοντας τη μνήμη στο πρόγραμμά σας, κάνετε περισσότερες διαθέσιμες για χρήση αργότερα.
Για παράδειγμα:
#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Value of the 2nd integer is %d",*(ptr + 2)); } free(ptr); }
Παραγωγή:
Value of the 2nd integer is 50
Η συνάρτηση calloc() στο C
Η συνάρτηση C calloc() σημαίνει συνεχόμενη κατανομή. Αυτή η λειτουργία χρησιμοποιείται για την εκχώρηση πολλαπλών μπλοκ μνήμης. Είναι μια συνάρτηση δυναμικής εκχώρησης μνήμης που χρησιμοποιείται για την κατανομή της μνήμης σε πολύπλοκες δομές δεδομένων όπως πίνακες και δομές.
Η συνάρτηση Malloc() χρησιμοποιείται για την εκχώρηση ενός μόνο μπλοκ χώρου μνήμης ενώ η calloc() στο C χρησιμοποιείται για την εκχώρηση πολλαπλών μπλοκ χώρου μνήμης. Κάθε μπλοκ που εκχωρείται από τη συνάρτηση calloc() έχει το ίδιο μέγεθος.
Σύνταξη της συνάρτησης calloc():
ptr = (cast_type *) calloc (n, size);
- Η παραπάνω πρόταση χρησιμοποιείται για την εκχώρηση n μπλοκ μνήμης ίδιου μεγέθους.
- Αφού εκχωρηθεί ο χώρος μνήμης, τότε όλα τα byte αρχικοποιούνται στο μηδέν.
- Ο δείκτης που βρίσκεται αυτήν τη στιγμή στο πρώτο byte του εκχωρημένου χώρου μνήμης επιστρέφεται.
Κάθε φορά που υπάρχει ένα σφάλμα κατά την κατανομή χώρου στη μνήμη, όπως η έλλειψη μνήμης, τότε επιστρέφεται ένας μηδενικός δείκτης.
Παράδειγμα calloc():
Το παρακάτω πρόγραμμα υπολογίζει το άθροισμα μιας αριθμητικής ακολουθίας.
#include <stdio.h> int main() { int i, * ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memory not allocated."); exit(0); } printf("Building and calculating the sequence sum of the first 10 terms \ n "); for (i = 0; i < 10; ++i) { * (ptr + i) = i; sum += * (ptr + i); } printf("Sum = %d", sum); free(ptr); return 0; }
Αποτέλεσμα:
Building and calculating the sequence sum of the first 10 terms Sum = 45
calloc() έναντι malloc(): Βασικές διαφορές
Ακολουθεί η βασική διαφορά μεταξύ malloc() εναντίον calloc() σε C:
Η συνάρτηση calloc() είναι γενικά πιο κατάλληλη και αποτελεσματική από αυτή της συνάρτησης malloc(). Ενώ και οι δύο συναρτήσεις χρησιμοποιούνται για την κατανομή χώρου στη μνήμη, η calloc() μπορεί να εκχωρήσει πολλά μπλοκ ταυτόχρονα. Δεν χρειάζεται να ζητάτε ένα μπλοκ μνήμης κάθε φορά. Η συνάρτηση calloc() χρησιμοποιείται σε πολύπλοκες δομές δεδομένων που απαιτούν μεγαλύτερο χώρο στη μνήμη.
Το μπλοκ μνήμης που εκχωρείται από ένα calloc() στο C είναι πάντα αρχικοποιημένο στο μηδέν ενώ στη συνάρτηση malloc() στο C, περιέχει πάντα μια τιμή σκουπιδιών.
συνάρτηση realloc() στο C
Χρησιμοποιώντας το C realloc() λειτουργία, μπορείτε να προσθέσετε περισσότερο μέγεθος μνήμης στην ήδη εκχωρημένη μνήμη. Επεκτείνει το τρέχον μπλοκ ενώ αφήνει το αρχικό περιεχόμενο ως έχει. Το realloc() στο C σημαίνει ανακατανομή μνήμης.
Το realloc() μπορεί επίσης να χρησιμοποιηθεί για τη μείωση του μεγέθους της μνήμης που είχε εκχωρηθεί προηγουμένως.
Σύνταξη της συνάρτησης realloc():
ptr = realloc (ptr,newsize);
Η παραπάνω δήλωση εκχωρεί έναν νέο χώρο μνήμης με καθορισμένο μέγεθος στη μεταβλητή newsize. Μετά την εκτέλεση της συνάρτησης, ο δείκτης θα επιστρέψει στο πρώτο byte του μπλοκ μνήμης. Το νέο μέγεθος μπορεί να είναι μεγαλύτερο ή μικρότερο από την προηγούμενη μνήμη. Δεν μπορούμε να είμαστε σίγουροι ότι εάν το μπλοκ που εκχωρήθηκε πρόσφατα θα δείχνει στην ίδια θέση με αυτή του προηγούμενου μπλοκ μνήμης. Αυτή η συνάρτηση θα αντιγράψει όλα τα προηγούμενα δεδομένα στη νέα περιοχή. Διασφαλίζει ότι τα δεδομένα θα παραμείνουν ασφαλή.
Παράδειγμα realloc():
#include <stdio.h> int main () { char *ptr; ptr = (char *) malloc(10); strcpy(ptr, "Programming"); printf(" %s, Address = %u\n", ptr, ptr); ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size strcat(ptr, " In 'C'"); printf(" %s, Address = %u\n", ptr, ptr); free(ptr); return 0; }
Κάθε φορά που η realloc() στο C καταλήγει σε μια ανεπιτυχή λειτουργία, επιστρέφει έναν μηδενικό δείκτη και τα προηγούμενα δεδομένα επίσης ελευθερώνονται.
Δυναμικοί πίνακες σε C
Ένας δυναμικός πίνακας στο C επιτρέπει στον αριθμό των στοιχείων να αυξάνεται ανάλογα με τις ανάγκες. C Οι δυναμικές συστοιχίες χρησιμοποιούνται ευρέως στους αλγόριθμους της επιστήμης των υπολογιστών.
Στο παρακάτω πρόγραμμα, δημιουργήσαμε και αλλάξαμε το μέγεθος ενός Dynamic array C
#include <stdio.h> int main() { int * arr_dynamic = NULL; int elements = 2, i; arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks for (i = 0; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elements = 4; arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements printf("After realloc\n"); for (i = 2; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }
Αποτέλεσμα του προγράμματος C Dynamic array στην οθόνη:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3
Περίληψη
- Μπορούμε να διαχειριστούμε δυναμικά τη μνήμη δημιουργώντας μπλοκ μνήμης όπως απαιτείται στο σωρό
- Στο C Dynamic Memory Allocation, η μνήμη εκχωρείται σε χρόνο εκτέλεσης.
- Η δυναμική εκχώρηση μνήμης επιτρέπει τον χειρισμό συμβολοσειρών και πινάκων των οποίων το μέγεθος είναι ευέλικτο και μπορεί να αλλάξει οποιαδήποτε στιγμή στο πρόγραμμά σας.
- Απαιτείται όταν δεν έχετε ιδέα πόση μνήμη πρόκειται να καταλάβει μια συγκεκριμένη δομή.
- Η Malloc() στο C είναι μια συνάρτηση δυναμικής εκχώρησης μνήμης που αντιπροσωπεύει την εκχώρηση μνήμης που μπλοκ μνήμης με το συγκεκριμένο μέγεθος αρχικοποιημένο σε μια τιμή σκουπιδιών
- Η Calloc() στο C είναι μια συνεχόμενη συνάρτηση εκχώρησης μνήμης που εκχωρεί πολλαπλά μπλοκ μνήμης τη φορά που αρχικοποιούνται στο 0
- Το Realloc() στο C χρησιμοποιείται για την ανακατανομή της μνήμης σύμφωνα με το καθορισμένο μέγεθος.
- Η συνάρτηση Free() χρησιμοποιείται για την εκκαθάριση της δυναμικά εκχωρημένης μνήμης.