Πίνακες δεικτών, δείκτες πινάκων, δείκτες δεικτών |
Το πρόγραμμα που βρίσκεται στο αρχείο BIGDYNL.C δίνει ένα παράδειγμα μαζικότερης δέσμευσης μνήμης με τη βοήθεια μιάς επαναληπτικής διαδικασίας και ενός πίνακα δεικτών. Ένας πίνακας δεικτών 12 θέσεων ορίζεται με τη δήλωση *pet[12]. Οι δείκτες αυτοί περιέχουν δειυθύνσεις που δείχνουν σε εγγραφές του τύπου animal. Επίσης δηλώνεται και ο απλός δείκτης point που δείχνει σε ίδιο τύπο εγγραφής. Τώρα που έχουμε 12 δείκτες είναι απλή δουλειά να γράψουμε μιά επανάληψη που που να δεσμεύει χώρο μνήμης γιά μία εγγραφή, να εκχωρεί τη διεύθυνση σε έναν δείκτη και στη συνέχεια να γεμίζει με κάποια δεδομένα τα πεδία της εγγραφής. Προφανώς μιά πιό πργαματική εφαρμογή θα περιείχε το άνοιγμα μιάς βάσης δεδομένων (ενός αρχείου) και το διάβασμα του περιεχόμενου του αρχείου στις αντίστοιχες εγγραφές γιά παραπέρα επεξεργασία. Επίσης στο τέλος του προγράμματος θα υπήρχε μιά αντίστοιχη διαδικασία αποθήκευσης των στοιχείων σε αρχείο σε συνδυασμό με την αποδέσμευση της μνήμης. Οι προτάσεις εκχώρησης και η εκτύπωση απλά δείχνουν τη μέθοδο πρόσβασης στα πεδία των εγγραφών. Το σημαντικό στοιχείο αυτού του προγράμματος είναι η δήλωση *pet[12] που περιγράφει έναν πίνακα δεικτών. Ας θυμηθούμε οτι στη C το όνομα ενός πίνακα αυτόματα ορίζει και έναν δείκτη που δείχνει στο πρώτο στοιχείο του πίνακα. Ο τύπος δεδομένου που δείχνει ο δείκτης ορίζεται και αυτός αυτόματα: είναι ο τύπος δεδομένου που αντιστοιχεί στα στοιχεία του πίνακα. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 12 years old. General is a Mixed Breed, and is 15 years old. General is a Mixed Breed, and is 10 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years old. General is a Mixed Breed, and is 4 years ol Το ερώτημα που τίθεται είναι: θα μπορούσαμε επομένως να δηλώσουμε ολόκληρο πίνακα μεταβλητών με τη χρήση ενός απλού δείκτη; Η κλασσική δήλωση ενός πίνακα, π.χ. some_type pet[12], πέρα από τον αυτόματο ορισμό του δείκτη pet που δείχνει σε δεδομένο του τύπου some_type δεσμεύει αυτόματα στο κύριο τμήμα μνήμης του προγράμματος (ή ακόμη και στη στοίβα) χώρο αρκετό γιά την αποθήκευση 12 μεταβλητών του τύπου some_type και επίσης αυτόματα εκχωρεί την διεύθυνση του πρώτου byte αυτού του χώρου στον δείκτη pet. Μπορούμε επομένως να υλοποιήσουμε σε δυναμική μορφή όλες τις λειτουργίες που περιγράψαμε εκτός από μία: την ομαδική δέσμευση 12 θέσεων μνήμης αντί της μιάς. Δεν αποτελεί έκπληξη οτι υπάρχει τέτοια συνάρτηση είναι η calloc με δήλωση προτύπου της μορφής char *calloc(unsigned int number, size); Οι συμβάσεις κλήσης της συνάρτησης calloc είναι ίδιες με αυτές της malloc με την επιπλέον παράμετρο number να καθορίζει τον αριθμό των θέσεων μνήμης προς δέσμευση. Επομένως οι προτάσεις some_type *pet; .... pet = (some_type *)calloc(12, sizeof(some_type)); ισοδυναμούν με τη δυναμική δήλωση ενός πίνακα, δηλαδή έχουμε έναν πίνακα που βρίσκεται στο σωρό αντί του κυρίου τμήματος μνήμης. Κατά τα άλλα οι τεχνικές πρόσβασης σε πίνακα μέσω δείκτη που είχαν ήδη αναπτυχθεί ίσχύουν ακριβώς. Η αποδέσμευση ενός δυναμικά ορισμένου πίνακα γίνεται με τη συνάρτηση free και έχει ως αποτέλεσμα την συνολική αποδέσμευση του αντίστοιχου χώρου μνήμης. Η τεχνική που αναπτύχθηκε γιά τη δημιουργία ενός πίνακα κατά την εκτέλεση ενός προγράμματος (δυναμικά δηλαδή) μπορεί να επεκταθεί και σε πολυδιάστατους πίνακες. Έτσι ο κλασσικός ορισμός του διδιάτσατου πίνακα που έχει τη μορφή pet[12][12] μπορεί να αντικατασταθεί από τους εναλλακτικούς ορισμούς *pet[12] ή **pet. Η πρώτη εναλλακτική δήλωση μπορεί να χρησιμοποιηθεί γιά να ορίσει 12 δυναμικά ορισμένους πίνακες μεταβλητών που θα δείχνονται μέσω των δεικτών pet[0] έως pet[11]. Έχουμε δηλαδή έναν διδιάστατο πίνακα με σταθερό αριθμό γραμμών αλλά μεταβλητό αριθμό στηλών. Η δεύτερη εναλλακτική δήλωση μπορεί να χρησιμοποιηθεί γιά να δημουργήσει έναν δυναμικά ορισμένο πίνακα δεικτών όπου ο κάθε δείκτης μπορεί να χρησιμοποιηθεί με τη σειρά του γιά να προσεγγιστεί ένας δυναμικά ορισμένος πίνακας μεταβλητών. Έχουμε δηλαδή έναν διδιάστατο πίνακα με μεταβλητό αριθμό γραμμών και στηλών. |
![]() |
![]() |
![]() |