ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ Τεχνολογικό Εκπαιδευτικό Ίδρυμα Πειραιά Δομημένος Προγραμματισμός Ενότητα 7: Δείκτες Κουκουλέτσος Κώστας Τμήμα Μηχανικών Ηλεκτρονικών Υπολογιστικών Συστημάτων
Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύπου άδειας χρήσης, η άδεια χρήσης αναφέρεται ρητώς.
Χρηματοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα. Το έργο «Ανοικτά Ακαδημαϊκά Μαθήματα στο Ανώτατο Εκπαιδευτικό Ίδρυμα Πειραιά Τεχνολογικού Τομέα» έχει χρηματοδοτήσει μόνο τη αναδιαμόρφωση του εκπαιδευτικού υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκή Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικούς πόρους.
Σκοποί ενότητας 1. Nα κατανοήσουν την έννοια του δείκτη προς μία μεταβλητή και τον τρόπο ορισμού ενός δείκτη. 2. Να εξοικειωθούν την χρήση τελεστών με δείκτες και με τις πράξεις με δείκτες 3. Να γνωρίσουν την σχέση μεταξύ δείκτη και πίνακα και να τον τρόπο αναφοράς σε στοιχεία του πίνακα με χρήση δείκτη 4. Να κατανοήσουν του ειδικούς δείκτες null και void καθώς και τους συνδυασμούς δείκτη με σταθερές
Περιεχόμενα ενότητας Μεταβλητές και Μνήμη Η Μνήμη του Υπολογιστή Ορισμός δείκτη Ο τελεστής * με δείκτες Χρήση των δεικτών Σύνοψη Πράξεις με δείκτες Δείκτες και τελεστές αύξησης και μείωσης Πίνακες και δείκτες Δείκτες τύπου void Παράμετροι συναρτήσεων και printf Δείκτες και σταθερές
Μεταβλήτες και Μνήμη Η μνήμη αποτελείται από θέσεις (cells) στις οποίες αποθηκεύονται δεδομένα. Κάθε θέση έχει την δική του διεύθυνση. Το μέγεθος κάθε κελιού είναι 1 byte. Μία μεταβλητή καταλαμβάνει μία ή περισσότερες συνεχόμενες θέσεις στην μνήμη. Μνήμη που καταλαμβάνει μία μεταβλητή Οι θέσεις (bytes) που καταλαμβάνει μία μεταβλητή εξαρτάται από τον τύπο του δεδομένου. Για τους γνωστούς τύπους οι θέσεις είναι» char 1 byte» int 4 bytes» float 4 bytes» double 8 bytes Για να υπολογιστεί το μέγεθος μίας μεταβλητής χρησιμοποιώ την συνάρτηση sizeof πχ:» printf("%d",sizeof(int)); // εμφανίζει τον αριθμό 4
Η Μνήμη του Υπολογιστή Μία μεταβλητή τύπου int καταλαμβάνει 4 bytes. Σχηματικά μπορούμε να αναπαραστήσουμε την εντολή με τον παρακάτω τρόπο Μία γλώσσα προγραμματισμού μας παρέχει ένα εύκολο τρόπο να προσπελάσουμε την μνήμη του υπολογιστή με τα ονόματα των μεταβλητών. Είναι ευθύνη του μεταγλωττιστή (compiler) να θυμάται τις διευθύνσεις με τα ονόματα των μεταβλητών. Ουσιαστικά τα ονόματα είναι συντομεύσεις για τις διευθύνσεις ώστε ο προγραμματιστής να δουλεύει πιο εύκολα.
Ορισμός δείκτη (1/2) Ο δείκτης είναι μία μεταβλητή που σαν περιεχόμενο έχει μία διεύθυνση της μνήμης. Πχ.» int a=11;» int * pa; H pa είναι μία μεταβλητή που δείχνει την διεύθυνση μίας μεταβλητής ακέραιου τύπου. Για να δώσω μία τιμή στο pa χρησιμοποιώ τον τελεστή διεύθυνσης & (reference operator)» pa=&a;
Ορισμός δείκτη (2/2) Η μεταβλητή pa έχει σαν περιεχόμενο την διεύθυνση της μεταβλητής a που δείχνει (&a = address of a ). Με τον τελεστή * μπορώ να εμφανίσω την τιμή που βρίσκεται στην διεύθυνση που δείχνει (περιέχει) ο δείκτης δηλαδή:» printf("%d",*pa); //εμφανίζει τον αριθμό 11
Ο τελεστής * με δείκτες Το σύμβολο * χρησιμοποιείται με δύο σκοπούς Για να δηλώσει δείκτες Σαν τελεστής έμμεσης αναφοράς (dereference operator, indirection operator) για την από-αναφοροποιηση (dereferencing) στην τιμή της μεταβλητής που δείχνει ένας δείκτης, δηλαδή o τελεστής επιτρέπει την έμμεση αναφορά σε τιμή μίας μεταβλητής.» double a = 11.5;» double *pa = &a; //dilonei deikti pros double» printf("%f", *pa); //dereferencing kai emfanisi timis
Παράδειγμα» int a=11,b=88 ;» int * pa;» pa=&a ;» printf("%d %d %x %x\n", a,*pa,&a,&pa,pa);» printf("%d %d\n", sizeof(int), sizeof(pa)); Παρατηρήστε ότι H διεύθυνση που έχει αποθηκευτεί η μεταβλητή a εμφανίζεται με το &a. Οι τιμές του a και *pa είναι οι ίδιες Το περιεχόμενο του δείκτη pa που είναι η διεύθυνση 22ff44 συμπίπτει με την διεύθυνση &a που έχει αποθηκευτεί η a.
Xρήση των δεικτών Τα κύρια προτερήματα χρήσης δείκτη είναι Στις συναρτήσεις όπου επιτρέπεται επιστροφή πολλών τιμών Στους πίνακες που επιτρέπεται δυναμική κατανομή μνήμης δηλαδή η διάσταση του πίνακα να αλλάζει κατά την διάρκεια εκτέλεσης του προγράμματος ανάλογα με τις ανάγκες Η δυναμική χρήση μνήμης επιτρέπει δημιουργία συνδεδεμένης λίστας και άλλων δομών που χρησιμοποιούνται σε αλγόριθμους.
Παρατηρήσεις (1/2) 1) Για τον ορισμό του ενός δείκτη τα παρακάτω είναι ισοδύναμα.» int* a;» int * a;» int *a; 2) Για τον ορισμό περισσοτέρων του ενός δεικτών ο τελεστής * πρέπει να επαναλαμβάνεται:» int * a,* b,* c, d; Όλες οι μεταβλητές εκτός από την d είναι τύπου δείκτη, ενώ η d είναι ακέραια μεταβλητή. 3) Ένας δείκτης είναι σαν μία ακεραίου τύπου μεταβλητή. Απλά σαν τιμή έχουν ένα 16-δικό αριθμό που αναφέρεται σε μία διεύθυνση όπου περιέχεται ένας αριθμός του ιδίου τύπου με τον τύπο του δείκτη.
Παρατηρήσεις (2/2) 4) Αν έχω δύο δείκτες» int * pa, * pb; τότε η εκχώρηση pa=pb σημαίνει ότι ο δείκτης pa έχει την ίδια τιμή με το δείκτη pb δηλαδή και οι δύο δείκτες δείχνουν προς την ιδία διεύθυνση, αυτή που δείχνει ο pb 5) To πλήθος των bytes που δεσμεύονται για ένα δείκτη είναι 4 και δεν έχει σημασία ο τύπος δεδομένων που δείχνει ο δείκτης.
Παράδειγμα εμφάνισης τιμών»int a=11,b=22, c=33;»int * pa, * pb, * pc;»»pa=&a ;»pb=&b;»pc=&c;»»printf("%d %d %x %x\n",a,*pa,&a,&pa,pa);»printf("%d %d %x %x\n",b,*pb,&b,&pb,pb);»»pa=pb;»printf("%d %d %x %x\n",a,*pa,&a,&pa,pa);»printf("%d %d %x %x\n",b,*pb,&b,&pb,pb);
Παράδειγμα με δείκτες Ποία η έξοδος του παρακάτω προγράμματος» printf("program \n");» int k=1,n=20;» int* d1,*d2;» k++;--n;» printf(" %d %d \n",n,k);» k=40; n=60;d2=&k;d1=&n;» printf("%d %d \n",*d1,*d2);» *d1=*d2; ++k;n+=10 ;» printf("%d %d %d %d \n",k,n,*d1,*d2);
Σύνοψη (1/2) 1) Η δήλωση ενός δείκτη γίνεται με» int * pa, *pb; float * pd; 2) Αφού δηλωθούν οι μεταβλητές αρχικοποίηση γίνεται με εκχωρήσεις διευθύνσεων» pa=&a ; pb=&b; pd=&d; 3) Με την εντολή pa=pb ο δείκτης pa και ο pb έχουν το ίδιο περιεχόμενο 4) Με την εντολή *pa=*pb το περιεχόμενο της μεταβλητής που δείχνει ο pa αλλάζει τιμή
Σύνοψη (2/2) 5) Η εντολή *pb=44 έχει σαν αποτέλεσμα τιμή της μεταβλητής που δείχνει ο δείκτης pb γίνεται 44 6) Το σύμβολο * χρησιμοποιείται για να δηλώσει δείκτες και επίσης χρησιμοποιείται σαν τελεστής έμμεσης αναφοράς (indirection operator dereference operator) για την από αναφοροποιηση (dereferencing) στην τιμή της μεταβλητής που δείχνει ένας δείκτης, δηλαδή για την έμμεση αναφορά σε τιμή μίας μεταβλητής. 7) Ένας δείκτης μετά την δήλωσή του έχει απροσδιόριστη τιμή Όλα αυτό παρουσιάζονται στο επόμενο παράδειγμα
Παράδειγμα σύνοψης Ποιά η έξοδος του παρακάτω προγράμματος:» int a=11,b=22 ;» float d=12.33;» int * pa, *pb; float * pd;»» pa=&a ; pb=&b; pd=&d;» printf("%d %d %f\n",*pa, *pb, *pd);» pa=pb;» printf("%d %d \n",*pa, *pb);» pa=&a ; pb=&b;» *pa=*pb;» printf("%d %d \n",*pa, *pb);»» int *pc;» printf("%d \n",*pc);
Πράξεις με δείκτες (1/2) Οι δείκτες είναι σαν ακέραιες μεταβλητές. Προσθέτοντας ή αφαιρώντας από ένα δείκτη προστίθεται ή αφαιρείται το μέγεθος του τύπου του δείκτη Αν pd είναι ένας δείκτης και Type είναι ο τύπος του δείκτη. η πράξη pd++ ισοδυναμεί με την pd + siseof(type) και η τιμή του δείκτη αλλάζει
Πράξεις με δείκτες (2/2) Η πράξη pd-- ισοδυναμεί με την pd - siseof(type) και η τιμή του δείκτη αλλάζει η πράξη pd+n ισοδυναμεί με την pd + n*siseof(type) και η τιμή του δείκτη δεν αλλάζει Η πράξη pd-- ισοδυναμεί με την pd - n*siseof(type) και η τιμή του δείκτη δεν αλλάζει
Παράδειγμα»int a[ ]={50,55,60,65};»int* dk=&a[2];»int m;»m=*dk+1; printf("%d\n",m); //emfanizei ton 61»m=*(dk+1); printf("%d\n",m); //emfanizei to 65»dk--; printf("%d\n",*dk); //emfanizei to 55
Δείκτες και τελεστές αύξησης και μείωσης (1/3) Οι τελεστές ++ και - - έχουν μεγαλύτερη προτεραιότητα από τον τελεστή * (indirection operator). Επομένως η έκφραση *p++ όταν ο p έχει οριστεί σαν δείκτης είναι ισοδύναμη με την *(p++), δηλαδή αυξάνεται η τιμή του p ώστε να δείχνει στο επόμενο στοιχείο. Όμως σε εκφράσεις του τύπου κ=*p++ επειδή το ++ χρησιμοποιείται σαν επίθεμα η παράσταση υπολογίζεται σαν την τιμή που δείχνει ο δείκτης πριν γίνει αύξηση του δείκτη δηλαδή στην κ=*p++ πρώτα εφαρμόζεται ο τελεστής * αποδίδεται η τιμή στο κ και μετά εφαρμόζεται ο τελεστής ++.
Δείκτες και τελεστές αύξησης και μείωσης (2/3) Επίσης θα πρέπει να τονιστεί ότι ακόμη και η χρήση παρενθέσεων δεν αλλάζει το αποτέλεσμα και η παράσταση κ= *(p++) υπολογίζεται σαν την τιμή που δείχνει ο δείκτης πριν γίνει αύξηση του δείκτη. Δηλαδή οι παραστάσεις κ=*p++ και η κ= *(p++) αποδίδουν την ίδια τιμή στο κ και πρώτα εφαρμόζεται ο τελεστής *και μετά ο τελεστής ++. Παράδειγμα» int a[2]={10,20}; int* d, k ;» d=&a[0]; k=*(d++); printf("z= %d *d= %d\n",k,*d);» d=&a[0]; k=*d++; printf("z= %d *d= %d\n",k,*d);» //kai stis dio forew emfanizontai oi idies times k=10 *d=20
Δείκτες και τελεστές αύξησης και μείωσης (3/3) Μόνο στην περίπτωση που χρησιμοποιηθεί το ++ σαν πρόθεμα τότε υπολογίζεται η τιμή που δείχνει ο δείκτης αφού γίνει η αύξηση» d=&a[0]; k=*++d;» printf("z= %d *d= %d\n",k,*d);» // emfanizontai oi times z=20 *d=20
Πίνακες και δείκτες Στην C δείκτες και πίνακες έχουν στενή σχέση. Ο πίνακας a είναι ένας δείκτης του ιδίου τύπου με τον πίνακα και δείχνει στο πρώτο στοιχείο του πίνακα. Όταν ο compiler συναντά a[n] το μετατρέπει σε *(a+n). Επομένως το 1ο στοιχειο a[0] του πίνακα είναι το *a 2ο στοιχειο a[1] του πίνακα είναι το *(a+1) 3ο στοιχειο a[2] του πίνακα είναι το *(a+2) κλπ. Γενικά ισχύει To *(a+i) είναι ισοδύναμο το a[i] Το a+i είναι ισοδύναμο με το &a[i]
Παράδειγμα 1» int i;» int a[ ]={50,55,60,65};» printf("%d ",*a); //emfanizetai 50» printf("%d\n",*(a+3)); //emfanizetai 65» for (i=0;i<4;i++)» printf("%d ",*(a+i)); Για να δηλώσω ένα δείκτη που δείχνει στο πρώτο στοιχείο του πίνακα μπορώ να το κάνω με δύο τρόπους: int a[ ]={50,55,60,65}; int * da=a; εναλλακτικά χρησιμοποιώ την δήλωση int da=&a[0]
Παράδειγμα 2 Να ορισθεί πίνακας με 4 θέσεις και να μηδενιστούν τα στοιχεία του 1ος τρόπος int k; float p1[4]; printf("times for p1\n"); for( k=0;k<4;k++){ p1[k]=0; printf("%5d",p1[k]);} 2ος τρόπος float p2[4]; printf("\ntimes for p1\n"); for(k=0;k<4;k++){ *(p2+k)=0; printf("%5d",p2[k]);}
Πίνακα = σταθερός δείκτης Το αναγνωριστικό ενός πίνακα (όνομα) είναι ένας δείκτης που δείχνει στο πρώτο στοιχείο του πίνακα. Ενώ επιτρέπεται αλλαγή τιμής σε μία μεταβλητή τύπου δείκτη δεν επιτρέπεται αλλαγή τιμής σε ένα δείκτη όταν αυτός έχει δηλωθεί ότι είναι πίνακας. Ο δείκτης στην περίπτωση αυτή είναι ένας constant pointer. Ο λόγος είναι ότι αν αλλάξει η τιμή δεν θα υπάρχει πρόσβαση στα υπόλοιπα στοιχεία του πίνακα. Το παρακάτω παράδειγμα εξηγεί το γεγονός αυτό.
Παράδειγμα»int pin[ ]={1,2,3,4,5};»printf("%d\n",*pin);»int * diktis, * dikt, k=100;»diktis=pin;»printf("%d %d %d %d\n",*diktis,diktis[1],*(pin+2),*(diktis+3));»» //pin=dikt;» /* Auto einai lathos giati o pin einai enas constant pointer kai den epitrepetai na allazei h timi toy */»» //pin=&k; //oute afto epitrepetai»»diktis=&k; //afto epitrepetai»printf("%d\n",*diktis);
Πίνακες και δείκτες (1/2) Γενικά πίνακες και δείκτες μπορούν να χρησιμοποιηθούν εναλλακτικά ο ένας στην θέση του άλλου με ορισμένους περιορισμούς που θα δούμε παρακάτω.» int pin[ ]={1,2,3,4,5};» int * diktis» diktis=pin Η εντολή diktis=pin έχει σαν αποτέλεσμα ο δείκτης να δείχνει στην πρώτη θέση του πίνακα pin γιατί ο πίνακας θεωρείται σαν δείκτης. Ισοδύναμα αυτό μπορεί να γραφεί και σαν diktis=pin[0]
Πίνακες και δείκτες (2/2) Οι παρακάτω εκφράσεις είναι ισοδύναμες» pin[2] *(diktis+2) *(pin+2) Επίσης οι παρακάτω εκφράσεις είναι ισοδύναμες» &pin[2] diktis+2 Ένας δείκτης μπορεί να συμπεριφερθεί και σαν πίνακας και μπορεί να γραφεί έχοντας σε αγκύλες ένα αύξοντα αριθμό που αναφέρεται σε μία θέση στην μνήμη δηλαδή» diktis[2] αναφέρεται στην θέση pin[2]
Παράδειγμα» //(D_pointers_16)» int pin[ ]={1,2,3,4,5};» int * diktis;» diktis=pin;» //prosvasi sta stoixeia toy pinaka» printf("%d %d %d \n", pin[2], *(pin+2), *(diktis+2));» //Isodinames ekfraseis gia diefthinsi» printf("%x %x \n", &pin[2], diktis+2);» //xrisi deikti san pinaka» printf("%d %d \n", pin[2],diktis[2]);
Δείκτες τύπου void Ένας δείκτης μπορεί να είναι τύπου void δηλαδή δεν δείχνει σε συγκεκριμένο τύπο. Χρησιμοποιείται για δείκτες που ο τύπος τους είναι απροσδιόριστος. Δείκτες τύπου void μπορούν (και είναι σύνηθες) να μετατρέπονται σε συγκεκριμένου τύπο με την χρήση του type casting Ο τύπος δείκτη void μπορεί να πάρει τιμή με την χρήση & όμως δεν μπορούμε να κάνουμε πράξεις σε αυτόν» void *da» int a; da=&a; Στον παραπάνω δείκτη da δεν μπορούμε να αυξήσουμε τον δείκτη (πχ da++) επειδή δεν είναι γνωστή ή αύξηση που πρέπει να γίνει
Αρχικοποίηση και Δείκτης τύπου null (1/2) Ένας δείκτης όταν ορίζεται έχει απροσδιόριστη τιμή. Οι παρακάτω εντολές έχουν απόβλεπες ή καταστροφικές συνέπειες (crash) για το πρόγραμμα γιατί ο δείκτης αν και ορίζεται δεν έχει τιμή δηλαδή δεν δείχνει σε μία έγκυρη διεύθυνση της μνήμης (πχ με εντολή pa=&x)» int *pa;» *pa=10; Συνηθίζεται ένας δείκτης που δεν έχει τιμή να του αποδίδεται μηδενική (null) τιμή (που πρακτικά είναι το 0) Η μηδενική τιμή χρησιμοποιείται ώστε ο δείκτης να μην δείχνει σε θέση της μνήμης που να έχει κάποιο δεδομένο. Ένας δείκτης null είναι δείκτης που ορίζεται σε πολλές βιβλιοθήκες της C (όπως η stdio.h) και είναι σταθερός τύπος δείκτη μηδενικού τύπου.
Αρχικοποίηση και Δείκτης τύπου null (2/2) Kατά σύμβαση ένας δείκτης που προσωρινά δεν δείχνει σε έγκυρη διεύθυνση της μνήμης του δίδεται σαν τιμή η μηδενική τιμή με την εντολή pa=0 ή ακόμη πιο καθαρά με την εντολή pa=null; H αρχικοποίηση δείκτη σε μηδενική τιμή δεν αποφεύγει λάθη στο πρόγραμμα. Το παρακάτω πρόγραμμα και πάλι κολλάει γιατί προσπαθεί στον δείκτη NULL να βάλει τιμή 10» int *pa=null;» *pa=10;
Παράμετροι συναρτήσεων και printf Προσοχή: (1/2) οι παράμετροι σε μία κλήση συνάρτησης υπολογίζονται από τα δεξιά στα αριστερά. Στην περίπτωση της printf (που είναι συνάρτηση) συμβαίνει ακριβώς το ίδιο και η σειρά εκτίμησης των παραμέτρων που υπολογίζονται είναι από τα δεξιά προς τα αριστερά.» int a = 1 ;» printf ( "%d %d %d", a, ++a, a++ ) ;
Παράμετροι συναρτήσεων και printf To αποτέλεσμα θα έπρεπε να είναι 1 2 3. Όμως το αποτέλεσα είναι 3 3 1 επειδή ισχύει ο ανωτέρω κανόνας. Τι εμφανίζει το παρακάτω;» a = 1 ;» printf ( "%d %d %d\n\n", a, a++, a++ ) ; (2/2)
Παράδειγμα
Δείκτες και σταθερές Μία μεταβλητή όταν δηλωθεί σταθερού τύπου δεν μπορεί να αλλάξει η τιμή της δηλαδή δεν το επιτρέπει ο μεταγλωττιστής :» const int PI=3.14; Μπορούμε να κάνουμε χρήση σταθεράς και σε δείκτες. Θα εξετάσουμε παρακάτω του εξής τύπους: constant pointer to a type (Σταθερούς δείκτες) pointer to a constant type (Δείκτες προς σταθερές) constant pointer to a constant type (Σταθερούς Δείκτες προς σταθερές)
Σταθεροί Δείκτες (constant pointer to a type) (1/2) Επίσης μπορούμε να δηλώσουμε σταθερό δείκτη δηλαδή ένα δείκτη που η τιμή του δεν αλλάζει και ο δείκτης δείχνει πάντα προς την ίδια διεύθυνση (constant pointer to a type). Ένας πίνακας είναι μία τέτοια μεταβλητή δηλαδή constant pointer (σταθερός δείκτης)» int n = 43;» //orismos constant pointer to an integer» int *const pn = &n;
Σταθεροί Δείκτες (constant pointer to a type) (2/2)» //pn++; Lathos increment of read-only variable» //pn=&k; Lathos increment of read-only variable Όμως επιτρέπεται αλλαγή της τιμής που δείχνει ο δείκτης δηλαδή επιτρέπεται η εντολή» *pn=203
Δείκτες προς σταθερές (pointer to a constant type) (1/2) Μπορούμε να δηλώσουμε δείκτη προς σταθερή τιμή με την χρήση const.» int k=55,m=44;» const int *pk=&k;» //*pk=22; H timi stin opoia exei prosvasi o deiktis» // den epitrepetai na allaxei H δεύτερη εντολή δηλώνει ένα pointer to a constant int
Δείκτες προς σταθερές (pointer to a constant type) (2/2) Επομένως απαγορεύεται να αλλάξει η τιμή που δείχνει ο δείκτης (σειρά 3) με την χρήση του δείκτη δηλαδή απαγορεύεται η εντολή:» *pk=22; Επιτρέπεται όμως να αλλάξει η τιμή της κ μέσω της μεταβλητής κ δηλαδή η παρακάτω εντολή δεν είναι λάθος γιατί δεν αλλάζει με την χρήση του δείκτη:» k++; Επίσης επιτρέπεται να αλλάξει ο δείκτης γιατί δεν είναι σταθερός δηλαδή οι παρακάτω δύο εντολές επιτρέπονται:» pk++; pk=&m;
Σταθεροί Δείκτες προς σταθερές (constant pointer to a constant type) Επίσης μπορούμε να δηλώσουμε σταθερό δείκτη προς σταθερή τιμή (constant pointer to a constant type)» int m = 11;» const int *const pm = &m; Δεν μπορούμε να αλλάξουμε την τιμή του δείκτης αλλά ούτε το περιεχόμενο που ο δείκτης δείχνει.
Τέλος Ενότητας