Δεικτών συνέχεια |
Η περιήγηση στη χώρα των δεικτών συνεχίζεται με τη βοήθεια του προγράμματος του αρχείου POINTER2.C. Οι δηλώσεις του προγράμματος ορίζουν έναν πίνακα 40 χαρακτήρων strg, δύο μεταβλητές χαρακτήρων one,two και έναν δείκτη σε χαρακτήρα there. Επίσης ορίζουν έναν πίνακα 100 ακεραίων list, μιά ακέραια μεταβλητή index και έναν δείκτη σε ακέραιο pt. Ας ασχοληθούμε με την πρώτη τετράδα προτάσεων. Η πρώτη πρόταση του προγράμματος αρχικοποιεί τον πίνακα με την αντιγραφή της συμβολοσειράς "This is a character string.". Προσέξτε τις δύο εκχωρήσεις που ακολουθούν. Η πρώτη είναι προφανής: η ματαβλητή χαρακτήρα one παίρνει την τιμή του μηδενικού στοιχείου της συμβολοσειράς strg. Η δεύτερη εκχώρηση κάνει ακριβώς το ίδιο: έχουμε πεί ήδη οτι το όνομα strg είναι ισοδύναμο με τη διεύθυνση &strg[0] δηλαδή το όνομα strg δίνει τη διεύθυνση του μηδενικού στοιχείου της συμβολοσειράς, ή γενικά τη διέυθυσνη της συμβολοσειράς. Επομένως Η έκφραση *strg είναι ισοδύναμη με την έκφραση *(&strg[0]) και με λόγια σημαίνει (Κανόνας 2) "η τρέχουσα τιμή της θέσης μνήμης που η διεύθυνσή της δίνεται από την έκφραση &strg[0] ή περιέχεται στη θέση μνήμης strg". Τι σημαίνει αυτό το τελευταίο; ΤΟ ΟΝΟΜΑ ΜΙΑΣ ΣΥΜΒΟΛΟΣΕΙΡΑΣ ΕΙΝΑΙ ΕΝΑΣ ΔΕΙΚΤΗΣ ΣΕ ΧΑΡΑΚΤΗΡΑ. Ας δούμε το συμπέρασμα αυτό σχηματικά στη μνήμη. |
![]() |
Όταν δηλώνεται ένας πίνακας χαρακτήρων 40 θέσεων τότε ο μεταφραστής πέρα από τις 40 θέσεις μνήμης (0 έως 39) που κρατά γιά τα στοιχεία του πίνακα, δεσμεύει επίσης και μία θέση μνήμης που είναι του τύπου δείκτη χαρακτήρα, έχει όνομα ίδιο με το όνομα του πίνακα χαρακτήρων και περιεχόμενα τη διέυθυνση του μηδενικού στοιχείου του πίνακα. Όλες οι υπόλοιπες θέσεις μνήμης κατ' αρχήν έχουν ακαθόριστες τιμές (συμβολίζονται με '??'). Με την συνάρτηση strcpy τα πρώτα 28 στοιχεία (0 έως 27) του πίνακα χαρακτήρων πάιρνουν τιμές, με τελεταίο τον μηδενικό χαρακτήρα, δηλαδή strg[27] = 0 έτσι ώστε ο πίνακας χαρακτήρων γίνεται συμβολοσειρά. Με την πρώτη εκχώρηση η μεταβλητή one παίρνει την τιμή 'Τ'. Με τη δεύτερη εκχώρηση η μεταβλητή two παίρνει την τιμή της θέσης μνήμης που δείχνει ο δείκτης strg άρα πάλι τη τιμή 'Τ'. Η πρόταση εκτύπωσης επιβεβαιώνει το γεγονός οτι οι δύο μεταβλητές έχουν την ίδια τιμή. Η δεύτερη ομάδα προτάσεων δείχνει τη δυνατότητα πρόσβασης σε τυχαίο στοιχείο του πίνακα με τη χρήση δεικτών. Η πρώτη πρόταση περιέχει τη συμβατική έκφραση strg[8] που όπως είδαμε σημαίνει "η τιμή του όγδοου στοιχείου του πίνακα strg". Η τιμή αυτή εκχωρείται στη μεταβλητή one. Η δεύτερη πρόταση περιρέχει την εναλλακτική έκφραση *(strg+8) που σημαίνει "η τιμή της θέσης μνήμης που η διεύθυνσή της δίνεται από την έκφραση strg+8". Τι είναι αυτό το 8 που προστίθεται στη τιμή strg; Ο μεταφραστής γνωρίζει οτι το strg είναι όνομα πίνακα χαρακτήρων, άρα είναι δείκτης χαρακτήρα. Επομένως η έκφραση strg+8 ισοδυναμεί με την έκφραση &strg[8] δηλαδή ο μεταφραστής προσθέτει στην τιμή του δείκτη strg τον σωστό αριθμό bytes (δηλαδή 1 * 8 bytes) ώστε η τιμή της έκφρασης δείχνει το όγδοο στοιχείο του πίνακα χαρακτήρων. Η τιμή αυτή εκχωρείται στη μεταβλητή two, όπως φαίνεται και από το αποτέλεσμα της πρότασης εκτύπωσης που ακολουθεί. Η κατάσταση στη μνήμη σχηματικά είναι |
![]() |
Η τρίτη ομάδα προτάσεων εξηγεί οτι μπορούμε οχι απλά να δημιουργούμε εκφράσεις με βάση την τιμή ενός δείκτη, του strg στη περίπτωσή μας, αλλά επίσης μπορούμε να εκχωρούμε τις τιμές αυτών των εκφράσεων σε άλλες μεταβλητές που είναι δείκτες χαρακτήρων. Ο δείκτης there μέχρι τώρα δεν έχει καμμία τιμή και με την εκχώρηση παίρνει την τιμή strg+10 ή ισοδύναμα &strg[10]. Δηλαδή η τιμή του δείκτη there είναι τώρα (Κανόνας 1) "η διεύθυνση της θέσης μνήμης που είναι αποθηκευμένο το δέκατο στοιχείο του πίνακα strg". ΟΙ δύο προτάσεις εκτύπωσης που ακολουθούν δεν δείχνουν ακριβώς την ισότητα των διευθύνσεων αλλά των περιεχομένων των διευθύνσεων. Θα μπορούσε όμως καποιος να εκτυπώσει και τις διευθύνσεις από περιέργεια. Η κατάσταση στη μνήμη είναι σχηματικά. |
![]() |
Αριθμητική δεικτών |
Ήδη εξηγήσαμε το νόημα που δίνεται στη πρόσθεση ενός ακεραίου σε έναν δείκτη, δηλαδή σε μιά διεύθυνση. Αντιστοιχεί με τη πρόσβαση σε θέσεις μνήμης με 'υψηλότερες' διεύθυσνη. Παρόμοια λογική ισχύει και γιά την αφαίρεση ακεραίων που αντιστοιχεί με την πρόσβαση σε θέσεις μνήμης με 'χαμηλότερες' διευθύνσεις. Η ακριβής απόσταση καθορίζεται από τον τύπο δεδομένων που δείχνει ο δείκτης. Εκφράσεις αυτο-αύξησης, αυτο-μείωσης ή σύνθετης εκχώρησης με προσθεση ή αφαίρεση ισχύουν και χρησιμοποιούνται ευρύτατα. Πράξεις πολλαπλασιασμού και διάιρεσης δεν επιτρέπονται. Επίσης δεν επιτρέπεται η πρόσθεση ή αφαίρεση υων τιμών δύο δεικτών μεταξύ των, ούτε η εκχώρηση απολύτων τιμών (σταθερών) σε δείκτες. |
Δείκτες ακεραίων |
Αυτά που έχουμε πεί γιά τους πίνακες χαρακτήρων ισχύουν ακριβώς και γιά πίνακες ακεραίων. Αυτό που αλλάζει είναι η απόσταση μεταξύ των στοιχείων του πίνακα, που επηρρεάζει τους υπολογισμούς των διευθύνσεων. Όμω; αυτό είναι δουλειά του μεταφραστή να το υπολογίσει, με βάση τον τύπο μεταβλητής που δείχνει ο δείκτης. Αρχικά δίνουμε τις τιμές 100 έως 199 στα στοιχεία του πίνακα list και στη συνέχεια εκχωρούμε στον δείκτη pt την διέυθυνση του 28ου στοιχείου του πίνακα, δηλαδή pt = list + 28 που ισοδυναμεί με pt = &list[28]. Τελικά εκτυπώνουμε την τιμή του 28ου στοιχείου του πίνακα με δύο διαφορετικούς τρόπους γιά να δείξουμε την ταυτότητα της έκφρασης. Το αποτέλεσμα του όλου προγράμματος δίνεται παρακάτω. The first output is T T The second output is a a The third output is c The fourth output is c The fifth output is 127 The sixth output is 127 |
![]() |
![]() |
![]() |