Δείκτες και εγγραφές |
Έχουμε εξηγήσει οτι το όνομα ένός πίνακα αποτελεί στην ουσία μία μεταβλητή δείκτη που περιέχει τη διεύθυνση του πρώτου στοιχείου. Στη περίπτωση του πίνακα εγγραφών το όνομα του πίνακα kid αντιστοιχεί σε ένα δείκτη που περιέχει τη διεύθυνση του πρώτου πεδίου της μηδενικής εγγραφής. Η διαχείριση ενός πίνακα με τη βοήθεια δεικτών μπορεί να επεκταθεί και στους πίνακες εγγραφών. Το πρόγραμμα του αρχείου STRUCT3.C εκτελεί τις ίδιες λειτοουργίες με το πρόγραμμα STRUCT2.C με τη διαφορά οτι η διαχείριση του πίνακα γίνεται με δείκτες αντί του καθιερωμένου τρόπου. Η πρώτη διαφορά εμφανίζεται στις δηλώσεις των μεταβλητών. Ορίζουμε μιά μεταβλητή point που είναι δείκτης σε μία εγγραφή. Προσοχή, όχι δείκτης στον πίνακα των εγγραφών αλλά σε μία εγγραφή. Επίσης ο δείκτης αυτός δεν μπορεί να 'δείξει' σε κάποια μεταβλητή άλλου τύπου παρά μόνο σε εγγραφή του συγκεκριμένου τύπου. Περισσότερα γιά αυτούς τους περιοσρισμούς στη συνέχεια. Η μεταβλητή extra είναι μιά ακόμη εγγραφή. Η επόμενη διαφορά εμφανίζεται στη χρήση των δεικτών στη πρώτη επανάληψη for γιά τη πρόσβαση στον πίνακα. Όπως έχουμε ήδη εξηγήσει ισχύει kids == &kids[0] == &kids[0].initial Το όνομα kids δεν μπορεί φυσικά να μεταβληθεί αλλά χρησιμοποιείται ως η βάση ενώ η μεταβλητή index χρησιμοποιείται ως μετρητής απόστασης από την βάση. Έτσι η έκφραση point = kids + index; εκχωρεί στο δείκτη point τη διέυθυνση της εγγραφής kids[index] δηλαδή η προηγούμενη έκφραση ισοδυναμεί με την έκφραση point = &kids[index]; |
Αριθμητική δεικτών |
Αυτό που έχει ιδιαίτερη σημασία και πρέπει να προσεχθεί είναι το γεγονός ότι ο μετφραστής της C προσθέτει τον ορθό αριθμό απόστασης index σε bytes στη βάση kids έτσι ώστε να παραχθεί η σωστή διεύθυνση. Η σωστή αριθμητική των δεικτών εξασφαλίζεται από τη δήλωση του τύπου του δείκτη. Αφού δηλαδή ο δείκτης point έχει δηλωθεί οτι δείχνει εγγραφές του συγκεκριμένου τύπου όλες οι αποστάσεις καθορίζονται με βάση το μέγεθος σε bytes της εγγραφής εκείνης. Το σχήμα που ακολουθεί δίνει ένα παράδειγμα |
![]() |
Στη πρώτη εκτέλεση της επανάληψης for η τιμή της μεταβλητής index είναι 0 άρα η τιμή του δείκτη point είναι 10005, δηλαδή ίση με τη διεύθυνση της βάσης kids ή &kids[0] ή &kids[0].initial. Στη δεύτερη εκτέλεση της επανάληψης η τιμή της index είναι 1 άρα η τιμή του δείκτη point είναι 10010 δηλαδή 10005+(5*1) bytes ή kids+(μέγεθος σε bytes της εγγραφής*index) ή ακόμη &kids[1] ή &kids[1].initial. Στην τελική εκτέλεση έχουμε index ίσο με 11 άρα η τιμή του δείκτη point είναι 10005+(5*11)=10060 ή ακόμη &kids[11] ή &kids[11].initial. Είναι τώρα καθαρό γιατί πρέπει να δηλωθεί ρητά οτι ο δείκτης point δείχνει εγγραφές συγκεκριμένου τύπου και γενικά γιατί κάθε δείκτης είναι συνδεδεμένος με μεταβλητή συγκεκριμένου τύπου. |
Δείκτες και πεδία εγγραφών |
Ας επιστρέψουμε στο πρόγραμμα. Όπως έχουμε πεί ο δείκτης point περιέχει τη διεύθυνση της αντίστοιχης εγγραφής. Γιά να έχουμε πρόσβαση στα πεδία της εγγραφής που δείχνεται από τον point χρησιμοποιούμε δύο εναλλακτικές μεθόδους. Έτσι, γιά παράδειγμα, η τιμή του πεδίου initial δίνεται από τις εκφράσεις (*point).initial ή point->initial Η έκφραση (*point) είναι η συνηθισμένη γιά τη πρόσβαση σε τιμή μεταβλητής που δείχνεται από δείκτη, ενώ η έκφραση point-> είναι ισοδύναμη αλλά μόνον γιά τη περίπτωση των εγγραφών. Το δεύτερο μέρος των εκφράσεων είναι ήδη γνωστό και είναι απαραίτητο γιατί η εγγραφή που δείχνεται περιέχει όχι μιά αλλά πολλές τιμές που ορίζονται από τα διάφορα πεδία. Προσοχή στο γεγονός οτι η έκφραση *point.initial είναι διαφορετική από την (*point).initial. Η δεύτερη έχει ήδη εξηγηθεί ενώ η πρώτη σημαίνει 'η τιμή που δείχνεται από το πεδίο initial της εγγραφής point'. Αυτό σημαίνει οτι το πεδίο initial θα έπρεπε να είναι τύπου δείκτη ενώ η μεταβλητή point θα έπρεπε να είναι του τύπου μεταβλητής κάποιας εγγραφής. Στις τελευταίες δύο προτάσεις του προγράμματος η μεταβλητή extra παίρνει την τιμή της εγγραφής kids[2] και αμέσως μετά την τιμή της εγγραφής *point δηλαδή της kids[11], αφού εκεί δείχνει ο point. Συμπερασματικά έχουμε τρείς μεθόδους πρόσβασης σε μιά εγγραφή και στα πεδία της. Έτσι οι εκφράσεις extra.initial, (*point).initial και point->initial είναι ισοδύναμες. Οι εναλλακτικές μορφές πρόσβασης, σε συνδυασμό και με πίνακες, φαίνονται στη επανάληψη εκτύπωσης του αποτελέσματος. A is 16 years old and got a grade of 84 B is 16 years old and got a grade of 84 C is 16 years old and got a grade of 92 D is 17 years old and got a grade of 84 E is 16 years old and got a grade of 57 F is 17 years old and got a grade of 84 G is 16 years old and got a grade of 92 H is 16 years old and got a grade of 84 I is 16 years old and got a grade of 84 J is 16 years old and got a grade of 84 K is 16 years old and got a grade of 84 L is 16 years old and got a grade of 84 |
![]() |
![]() |
![]() |