τα στοιχεία επικοινωνίας μου
Ταχυδρομείο[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
1. Βασική κατάσταση
Η διαχείριση μνήμης της γλώσσας C χωρίζεται σε δύο μέρη: διαχείριση συστήματος και διαχείριση εγχειριδίου χρήστη προγραμματιστή. Η μνήμη που διαχειρίζεται το σύστημα είναι κυρίως οι μεταβλητές (τοπικές μεταβλητές) μέσα στη συνάρτηση , το λειτουργικό σύστημα το ξεφορτώνει αυτόματα από τη μνήμη. Η μνήμη που διαχειρίζεται χειροκίνητα ο χρήστης είναι κυρίως μεταβλητές (καθολικές μεταβλητές) που υπάρχουν σε όλη τη διαδικασία εκτέλεσης του προγράμματος Η περιοχή μνήμης όπου βρίσκεται αυτό το τμήμα ονομάζεται "περιοχή σωρού". από τον χρήστη. Εάν ξεχάσετε να το απελευθερώσετε μετά τη χρήση, θα συνεχίσει να καταλαμβάνει μνήμη μέχρι να παραδοθεί στο λειτουργικό σύστημα κατά την έξοδο του προγράμματος.
2. κενός δείκτης
Στον χώρο μνήμης στον υπολογιστή εκχωρείται ένας μοναδικός κωδικός διεύθυνσης και η καθορισμένη περιοχή μνήμης μπορεί να βρεθεί μέσω του δείκτη μνήμης. Οι μεταβλητές δείκτη πρέπει να έχουν έναν τύπο, για παράδειγμα: int* p=&x δηλώνει έναν δείκτη τύπου int, ο οποίος δείχνει τη διεύθυνση της ακέραιας μεταβλητής x Όταν ο μεταγλωττιστής λαμβάνει τα δεδομένα από αυτήν τη διεύθυνση τα δεδομένα αποθηκεύονται. Όταν δεν είστε βέβαιοι για το είδος των δεδομένων που αποθηκεύονται και απλώς θέλετε να βρείτε πρώτα τη διεύθυνση της μνήμης μπλοκ, χρησιμοποιείται ο δείκτης τύπου κενού. Ένας δείκτης κενού τύπου ονομάζεται επίσης δείκτης αόριστου τύπου και μπορεί να δείχνει σε οποιοδήποτε τύπο δεδομένων.
Οι δείκτες κενού τύπου μπορούν να μετατραπούν σε δείκτες άλλων τύπων και δεν υπάρχει τίποτα ιδιαίτερο στη χρήση τους, εκτός από το ότι το αποθηκευμένο περιεχόμενο δεν μπορεί να αναλυθεί μέσω της μεθόδου "*".
int x = 10; //Δήλωση ακέραιου αριθμού x
void* p = &x; //Δηλώστε τον κενό δείκτη και τοποθετήστε τον δείκτη στη διεύθυνση του x, υποδεικνύοντας ότι ο δείκτης int (&x) μετατρέπεται σε δείκτη κενού.
int* q = p;
printf( "%in", *q );
Δώστε προσοχή στη διαφορά μεταξύ void* και void: το void είναι χωρίς τύπο και όταν χρησιμοποιείται για να δηλώσει μια συνάρτηση, σημαίνει ότι δεν υπάρχει τιμή επιστροφής ενώ το void*, αν και είναι άτυπο, αλλά έχει δείκτη, επιστρέφει κάτι.
3. Λειτουργίες που σχετίζονται με τη διαχείριση της μνήμης
1, malloc()
Αυτή η συνάρτηση μπορεί να απομνημονευθεί χωριστά.
Λειτουργία: αίτηση για ένα μπλοκ συνεχούς μνήμης από την περιοχή του σωρού (υπενθύμιση: η μνήμη της περιοχής σωρού πρέπει να διαχειρίζεται ο προγραμματιστής και πρέπει να καταστραφεί μετά τη χρήση. Αυτό θα πρέπει να θυμάστε πάντα τη μορφή χρήσης: malloc (ανατρέξτε στο 1).
Παράμετροι: Η παράμετρος 1 είναι το μέγεθος του μπλοκ μνήμης (ένας μη αρνητικός ακέραιος του τύπου size_t, η επιστρεφόμενη τιμή του sizeof είναι αυτού του τύπου)
Επιστρεφόμενη τιμή: δείκτης void* (θα χρησιμοποιήσουμε όποιον τύπο δείκτη χρησιμοποιούμε για να λάβουμε την εκχωρημένη μνήμη)
Χρήση: Οι μεταβλητές που δηλώνονται χρησιμοποιώντας τη συνάρτηση malloc βρίσκονται στην περιοχή του σωρού, επομένως χρησιμοποιείται συχνά η μέθοδος ανώνυμης δήλωσης, δηλαδή, αντί να χρησιμοποιεί τη μέθοδο διεύθυνσης συγκεκριμένων μεταβλητών, το malloc επιστρέφει απευθείας τον δείκτη, όπως φαίνεται παρακάτω:
int* ptr = (int*) malloc(sizeof(int) //Μια μεταβλητή δείκτη int δηλώνεται στην περιοχή heap
Η αναγκαστική μετατροπή σε παρένθεση δεν είναι απαραίτητη, επιστρέφει void*, η οποία μπορεί να ληφθεί με int*.
Προφυλάξεις:
α Χρησιμοποιήστε τη συνάρτηση malloc για συμπερίληψη<stdlib.h>αρχείο κεφαλίδας, όπως μόνο περιέχει<stdio.h> Μεταγλωττίζεται καλά, αλλά δεν λειτουργεί σωστά, να το έχετε υπόψη σας.
β) Εκχωρήστε τιμή σε ptr: *ptr=1000;.
γ. Χρησιμοποιήστε το malloc σε συνδυασμό με το δωρεάν (το οποίο θα συναντήσετε αργότερα).
δ) Το Malloc μπορεί να μην είναι επιτυχές στην εκχώρηση διευθύνσεων.
ε. Το malloc εκχωρεί μόνο μνήμη, ανεξάρτητα από την προετοιμασία, πρέπει να κληθεί μια άλλη συνάρτηση.
στ. Η πιο συχνά χρησιμοποιούμενη ευκαιρία για malloc είναι η εκχώρηση μνήμης για πίνακες και προσαρμοσμένες δομές δεδομένων.
2, memset()
Λειτουργία: Εκχωρήστε μια αρχική τιμή σε κάθε byte στο μπλοκ μνήμης στο οποίο δείχνει ένας δείκτης.
Παράμετροι: Παράμετρος 1 Δείκτης που δείχνει προς τη μνήμη στόχο Παράμετρος 2 Περιεχόμενο ανάθεσης (τιμή κωδικού ASCII τύπου int ή χαρακτήρας τύπου χαρακτήρων) Παράμετρος 3 Αριθμός byte που θα εκχωρηθούν (τύπος μεγέθους_t)
Επιστρεφόμενη τιμή: Επιστρέφει τον δείκτη που είναι στραμμένος στη μνήμη-στόχο Δεν έχει νόημα η λήψη, όπως και η παράμετρος 1.
Χρήση: memset(ptrDestMem,'A',sizeof(char)*1024) //Εκχώρηση χαρακτήρα Α σε κάθε byte ενός μπλοκ μνήμης με μήκος 1024 byte
Προφυλάξεις:
α. Το αρχείο κεφαλίδας στο οποίο ανήκει αυτή η συνάρτηση<string.h> , ορισμένοι μεταγλωττιστές μπορούν να χρησιμοποιηθούν κανονικά χωρίς να συμπεριλαμβάνεται αυτό το αρχείο κεφαλίδας Εάν παρουσιαστεί σφάλμα εκτέλεσης, συμπεριλάβετε το.
b Σημειώστε ότι το memset είναι μια λειτουργία σε byte (όχι bit αναφέρεται στον αριθμό των byte που πρέπει να εκχωρηθούν, τα οποία μπορεί να είναι μικρότερα από ή ίσα με τον αριθμό των byte στη μνήμη-στόχο, αλλά δεν μπορούν να υπερβούν το όριο).
γ Η τιμή της παραμέτρου 2 δεν μπορεί να υπερβεί ό,τι μπορεί να χωρέσει κατά ένα byte (τύπος int 255, δεν μπορεί να γραφτεί).
2, δωρεάν ()
Λειτουργία: Λειτουργία σε συνδυασμό με malloc, που χρησιμοποιείται για την απελευθέρωση της μνήμης που εκχωρείται από τη λειτουργία malloc και την αποτροπή διαρροών μνήμης
Παράμετροι: δείκτης που επιστρέφεται από τη συνάρτηση malloc
Χρήση: δωρεάν (ptr);
Προφυλάξεις:
α. Τα αρχεία κεφαλίδας που πρέπει να περιλαμβάνονται όταν χρησιμοποιείτε δωρεάν<stdlib.h> , μην ξεχνάς.
β Η ελεύθερη λειτουργία μπορεί να εκτελεστεί μόνο μία φορά και η ίδια διεύθυνση μνήμης δεν μπορεί να απελευθερωθεί επανειλημμένα και ο δείκτης που απελευθερώθηκε δεν μπορεί να χρησιμοποιηθεί ξανά.
c Είναι καλύτερο να γράψετε malloc και free πρώτα σε ζευγάρια και μετά να εισαγάγετε άλλους κωδικούς στη μέση για να αποφύγετε τη λήθη.
3, realloc()
re, δηλαδή πάλι, συντομογραφία κατανομής εκχώρησης, μαζί σημαίνει εκ νέου εκχώρηση μνήμης
Λειτουργία: Τροποποιήστε το μέγεθος του εκχωρημένου μπλοκ μνήμης (αύξηση ή μείωση).
Παράμετροι: Παράμετρος 1, αρχικός δείκτης μπλοκ μνήμης, παράμετρος 2, μέγεθος μπλοκ μνήμης μετά από αύξηση ή μείωση (τύπος σταθερού μεγέθους_t)
Επιστρεφόμενη τιμή: δείκτης void* (μπορεί να ληφθεί από την αρχική μεταβλητή τύπου δείκτη)
Χρήση: void* newPtr=realloc(ptr,sizeof(int)*10);
Προφυλάξεις:
α Όταν χρησιμοποιείτε τη συνάρτηση realloc, πρέπει επίσης να συμπεριληφθεί<stdlib.h> .
β Το μπλοκ μνήμης που δείχνει ο αρχικός δείκτης έχει αντικατασταθεί από τον νέο δείκτη, επομένως είναι ο νέος δείκτης που πρέπει να ελευθερωθεί όταν τελειώσει το πρόγραμμα και ο αρχικός δείκτης δεν χρειάζεται να ελευθερωθεί, διαφορετικά θα υπάρξει σφάλμα λειτουργίας. συμβούν.
γ. Το realloc μπορεί να αποτύχει να εκχωρήσει μνήμη και να επιστρέψει NULL εάν αποτύχει, επομένως είναι καλύτερο να προσθέσετε μια εντολή if για να την αντιμετωπίσετε.
4. Παραδείγματα εφαρμογών
- #include<stdio.h>
- #include<stdlib.h> //malloc、free、realloc
- #include<string.h> //memset
- int main(void)
- {
- //A void指针的使用
- float PI = 3.14159;
- void* pPI = &PI;
- float r = 2.5;
- printf("半径2.5圆的面积:%fn", r * r * *(float*)pPI);//*(float*)pPI—pPI强转为float指针后再解出指向的值
- //B malloc、memset、free函数使用
- int n = 8;
- void* pMyMem = malloc(sizeof(char)*n); //char占1字节,malloc分派n字节的内存,返给void指针
- if (pMyMem == NULL)return 0; //若分派内存失败,程序结束
- void* myMem2=memset(pMyMem,'B',sizeof(char)*8); //对malloc分派的内存区块个字节都写入字符'B'。
- //并用myMem2接收返回的指针
- if (pMyMem == myMem2)printf("memset写入区块指针与其返回的指针相同n");
- char* transCh = pMyMem; //将void指针转成char型指针
- printf("显示写入内容:");
- for (int i = 0; i < n; i++)
- {
- printf("%c ", *transCh); //显示写入的字符
- transCh++;
- }
- printf("n");//换行
- free(pMyMem); //释放malloc函数分派的内存
- //free(ch); //只有malloc分派的内存才需要释放,且只释放一次(这里会报错)
- //C realloc、free函数的使用
- int* pMem = malloc(sizeof(int)*5);
- if (pMem == NULL)return 0;
- for (int i = 0; i < 5; i++) pMem[i] = (i+1)*10;
- for (int i = 0; i < 5; i++) printf("%i ", pMem[i]);
- printf("n重新增加分派内存后n");
- int* newpMem = realloc(pMem, sizeof(int) * 10);
- if (newpMem == NULL)return 0;
- for (int i = 0; i < 10; i++) newpMem[i] = (i + 1) * 10;
- for (int i = 0; i < 10; i++)printf("%i ", newpMem[i]);
- free(newpMem); //释放realloc的内存
- //free(pMem);//pMem已被重置,不能再释放,此语句会造成运行失败
- getchar(); //暂停屏幕
- return 0;
- }