Δομημένος Προγραμματισμός (ΤΛ1006)

Σχετικά έγγραφα
Προγραμματισμός Η/Υ (ΤΛ2007 )

Δομημένος Προγραμματισμός (ΤΛ1006)

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δομημένος Προγραμματισμός (ΤΛ1006)

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δομημένος Προγραμματισμός

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

ΑΣΚΗΣΗ 6: ΔΕΙΚΤΕΣ. Σκοπός της Άσκησης. 1. Εισαγωγικά στοιχεία για τους Δείκτες

Δομημένος Προγραμματισμός (ΤΛ1006)

Δομημένος Προγραμματισμός (ΤΛ1006)

Δομές Δεδομένων (Εργ.) Ακ. Έτος Διδάσκων: Ευάγγελος Σπύρου. Εργαστήριο 3 Επανάληψη Γ μέρος

Η γλώσσα προγραμματισμού C

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Προγραμματισμός ΙI (Θ)

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δομημένος Προγραμματισμός (ΤΛ1006)

Η γλώσσα προγραμματισμού C

Προγραμματισμός Ι (ΗΥ120)

Διαδικασιακός Προγραμματισμός

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Προγραμματισμός Η/Υ (ΤΛ2007 )

Διαδικασιακός Προγραμματισμός

Δομημένος Προγραμματισμός (ΤΛ1006)

ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

Διάλεξη 5: Δείκτες και Συναρτήσεις

Διαδικασιακός Προγραμματισμός

Προγραμματισμός Η/Υ (ΤΛ2007 )

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

Εισαγωγή στον Προγραμματισμό

Δομημένος Προγραμματισμός (ΤΛ1006)

Διαδικασιακός Προγραμματισμός

Η γλώσσα προγραμματισμού C

Η γλώσσα προγραμματισμού C

Προγραμματισμός Η/Υ (ΤΛ2007 )

scanf() scanf() stdin scanf() printf() int float double %lf float

Η πρώτη παράμετρος είναι ένα αλφαριθμητικό μορφοποίησης

Προγραμματισμός Ι. Χαρακτήρες. Πανεπιστήμιο Πελοποννήσου Τμήμα Πληροφορικής & Τηλεπικοινωνιών

Διαδικασιακός Προγραμματισμός

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δείκτες και Συναρτήσεις (Κεφάλαιο 11, KNK-2ED)

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Προγραμματισμός Η/Υ Ι (Χρήση της C) 6 η Θεωρία ΜΟΝΟΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ

6. ΠΙΝΑΚΕΣ & ΑΛΦΑΡΙΘΜΗΤΙΚΑ

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

Η βασική συνάρτηση προγράμματος main()

Κεφάλαιο , 3.2: Συναρτήσεις II. (Διάλεξη 12)

Δομημένος Προγραμματισμός (ΤΛ1006)

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Δομημένος Προγραμματισμός

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ & ΥΠΟΛΟΓΙΣΤΙΚΗ ΦΥΣΙΚΗ

Μεθόδων Επίλυσης Προβλημάτων

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. (Διάλεξη 14) Παράδειγμα: Αλλαγή τιμής μεταβλητής μόνο τοπικά

Ορισμός μεταβλητών δεικτών και αρχικοποίηση

Διαδικαστικός Προγραμματισμός

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Προγραμματισμός Ι. Δομές & Ενώσεις. Πανεπιστήμιο Πελοποννήσου Τμήμα Πληροφορικής & Τηλεπικοινωνιών

Εισαγωγή στον Προγραμματισμό με C++

Προγραμματισμός Ι (ΗΥ120)

Μεθόδων Επίλυσης Προβλημάτων

ΤΕΜ-101 Εισαγωγή στους Η/Υ Εξεταστική Ιανουαρίου 2011 Θέματα Β

3ο σετ σημειώσεων - Πίνακες, συμβολοσειρές, συναρτήσεις

Διάλεξη 11η: Δείκτες, μέρος 1

Προγραμματισμός Ι (ΗΥ120)

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

Ενδεικτική περιγραφή μαθήματος

Υπολογισμός - Συλλογή Δεδομένων - Πίνακες

Εισαγωγή στον Προγραμματισμό

Στόχοι και αντικείμενο ενότητας. Εκφράσεις. Η έννοια του τελεστή. #2.. Εισαγωγή στη C (Μέρος Δεύτερο) Η έννοια του Τελεστή

Δομημένος Προγραμματισμός (ΤΛ1006)

Συναρτήσεις. Εισαγωγή

Ανάπτυξη και Σχεδίαση Λογισμικού

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. Δείκτες (Διάλεξη 14)

Πίνακες. 1 Πίνακες. 30 Μαρτίου 2014

Εργαστήριο 2ο. Περίγραμμα Εργαστηριακής Άσκησης

Προγραμματισμός Ι (ΗΥ120)

Προγραμματισμός Υπολογιστών & Υπολογιστική Φυσική

Εισαγωγή στον Προγραµµατισµό «C»

Κεφάλαιο 7: Υποπρογράμματα. Αρχές Γλωσσών Προγραμματισμού και Μεταφραστών

Προγραμματισμός Η/Υ 1 (Εργαστήριο)

7. ΕΙΣΑΓΩΓΗ ΣΤΙΣ ΣΥΝΑΡΤΗΣΕΙΣ

Διδάσκων: Παναγιώτης Ανδρέου

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

5ο σετ σημειώσεων - Δείκτες

Ηβασικήσυνάρτηση προγράμματος main()

ΥΠΟΛΟΓΙΣΤΕΣ ΙΙ. Τι περιλαμβάνει μια μεταβλητή; ΔΕΙΚΤΕΣ. Διεύθυνση μεταβλητής. Δείκτης

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

Προγραμματισμός Υπολογιστών & Υπολογιστική Φυσική

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Κεφάλαιο 7: Υπορουτίνες

10 η Διάλεξη C++ - Πίνακες. Δρ. Χρήστος Δρόσος ΑΕΙ ΠΕΙΡΑΙΑ ΤΤ ΤΜΗΜΑ ΑΥΤΟΜΑΤΙΣΜΟΥ

Υπολογισμός - Εντολές Επανάληψης

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Προγραμματισμός Η/Υ (ΤΛ2007 )

Κεφάλαιο 3.1, : Συναρτήσεις I. (Διάλεξη 11)

Τεχνολογία και Προγραμματισμός Υπολογιστών. Η γλώσσα προγραμματισμού C

Εισαγωγή στον Προγραμματισμό με C++

Αρχές Γλωσσών Προγραμματισμού και Μεταφραστών

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ & ΥΠΟΛΟΓΙΣΤΙΚΗ ΦΥΣΙΚΗ

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Εισαγωγή στον Προγραμματισμό

Transcript:

Τεχνολογικό Εκπαιδευτικό Ίδρυμα Κρήτης Σχολή Εφαρμοσμένων Επιστημών Τμήμα Ηλεκτρονικών Μηχανικών Τομέας Αυτοματισμού και Πληροφορικής Δομημένος Προγραμματισμός (ΤΛ1006) Δρ. Μηχ. Νικόλαος Πετράκης, Καθηγητής Εφαρμογών (npet@chania.teicrete.gr) Έβδομη (7 η ) τρίωρη διάλεξη. Ιστοσελίδα Μαθήματος: https://eclass.chania.teicrete.gr/courses/el106 Εξάμηνο: Χειμερινό 2017-18

Γενικά περί μεταβλητών H μνήμη RAM ενός Η/Υ αποτελείται από πολλά εκατομμύρια διαδοχικές θέσεις αποθήκευσης και κάθε θέση προσδιορίζεται από μία μοναδική διεύθυνση. Όταν δηλώνουμε μία μεταβλητή σε ένα πρόγραμμα της C, o μεταγλωττιστής δεσμεύει μία περιοχή μνήμης (κατάλληλου μεγέθους), η οποία ξεκινάει από μια θέση μνήμης με μοναδική διεύθυνση για να αποθηκεύσει αυτή τη μεταβλητή. Ο μεταγλωττιστής συσχετίζει αυτή τη διεύθυνση με το όνομα της μεταβλητής. 2

Μεταβλητές τοπικής εμβέλειας Στο σώμα μίας συνάρτησης μπορούμε να ορίσουμε μεταβλητές. Οι μεταβλητές αυτές έχουν περίοδο ζωής όσο διαρκεί η λειτουργία της συνάρτησης. Οι μεταβλητές αυτές έχουν εμβέλεια και δικαίωμα χρήσης μόνο στο σώμα της συγκεκριμένης συνάρτησης που ορίζονται. Αυτό ισχύει ακόμα και αν υπάρχει μεταβλητή σε άλλο σημείο στο πρόγραμμα με το ίδιο όνομα. Είναι γενικά κακό προγραμματιστικό στυλ να χρησιμοποιούμε το ίδιο όνομα για μία τοπική μεταβλητή (local variable) και για μία καθολική μεταβλητή (global variable). 3

#include <stdio.h> int sum(int, int); int i, j, k; Παράδειγμα void main() Μεταβλητές καθολικής εμβέλειας { printf("enter two numbers:"); scanf("%d%d", &i, &j); k = sum( i, j ); } printf("the sum of %d, %d is: %d", i, j, k); int sum(int number1, int number2) { int m; m = number1 + number2; return m; } Μεταβλητή τοπικής εμβέλειας 4

Κλήση της συνάρτησης Μία συνάρτηση μπορεί να κληθεί με δύο τρόπους: 1. χρησιμοποιώντας το όνομά της και τη λίστα των ορισμάτων της σε μια αυτόνομη πρόταση π.χ.... wait(12);... Εδώ θεωρούμε ότι η συνάρτηση δεν επιστρέφει κάποιο αποτέλεσμα αλλά έχει κάποιες παράπλευρες λειτουργίες. 2. χρησιμοποιώντας το όνομά της και τη λίστα των ορισμάτων της σε μια έκφραση π.χ.... k = sum(2, 10);... Εδώ θεωρούμε ότι η συνάρτηση επιστρέφει κάποιο αποτέλεσμα. 5

Μηχανισμός κλήσης Ο μηχανισμός κλήσης μιας συνάρτησης βασίζεται: 1. Στην συσχέτιση του ονόματος της συνάρτησης στο σημείο ορισμού της με το όνομα της συνάρτησης στο σημείο κλήσης. 2. Στη συσχέτιση του πλήθους των παραμέτρων της συνάρτησης στο σημείο ορισμού της με το πλήθος των παραμέτρων της συνάρτησης στο σημείο κλήσης. 3. Στη συσχέτιση του τύπου επιστροφής της συνάρτησης στο σημείο ορισμού της με τη χρήση του αποτελέσματος της συνάρτησης στην έκφραση που υπάρχει η κλήση της συνάρτησης. Όπως θα δούμε αργότερα, υπάρχουν δύο τρόποι διοχέτευσης δεδομένων προς τις συναρτήσεις Μεταβίβαση κατά αξία (Pass by value) Μεταβίβαση κατά αναφορά (Pass by reference) 6

Επιστροφή αποτελέσματος Όταν μία συνάρτηση καλείται: Ο κώδικας στο σημείο κλήσης της συνάρτησης σταματά. Ο κώδικας στο σώμα της συνάρτησης εκτελείται. Εάν η συνάρτηση που καλείται έχει παραμέτρους, οι παράμετροι παίρνουν τιμές από τις τιμές των ορισμάτων στο σημείο κλήσης. Τα ορίσματα και οι παράμετροι αντιστοιχίζονται ανάλογα με τη θέση τους και το τύπο τους (το πρώτο όρισμα με τη πρώτη παράμετρο, το δεύτερο όρισμα με τη δεύτερη παράμετρο κ.ο.κ.). Το αποτέλεσμα της συνάρτησης επιστρέφεται στο σημείο κλήσης με την βοήθεια της εντολής return return <έκφραση> ; Ο κώδικας ακριβώς μετά από το σημείο κλήσης συνεχίζει την λειτουργία του. 7

#include <stdio.h> int x, y, z; int larger_of(int, int); Παράδειγμα main() { printf("enter two different integer values : "); scanf("%d%d", &x, &y); z = larger_of(x, y); printf("\nthe larger value of %d, %d is %d", x, y, z); } int larger_of(int a, int b) { if (a > b) return a; else return b; } Η διοχέτευση των παραμέτρων της συνάρτησης larger_of γίνεται με την αντιστοίχιση των μεταβλητών x, y στο σημείο κλήσης με τις παραμέτρους a, b αντίστοιχα, στο σημείο ορισμού της συνάρτησης 8

Παράδειγμα x = half(third(square(half(y)))); a = half(y); b = square(a); c = third(b); x = half(c); Το πρόγραμμα καλεί πρώτα τη half() διοχετεύοντάς της την y ως όρισμα. Όταν η εκτέλεση επιστρέψει από τη half(), το πρόγραμμα καλεί την square() διοχετεύοντάς της την τιμή επιστροφής τής half() ως όρισμα, κτλ. 9

Καλή πρακτική Μην επιστρέφετε μία τιμή με διαφορετικό τύπο από τον τύπο της συνάρτησης. Μην αφήνετε συναρτήσεις να γίνονται μακροσκελείς. Κάθε συνάρτηση για μία εργασία. 10

Εισαγωγή στους δείκτες διεύθυνσης (pointers) Οι μεταβλητές που έχουμε δει μέχρι τώρα: 1. Είναι ή απλού τύπου (short int, int, float, double, long double, char), ή πιο σύνθετου τύπου όπως διατάξεις τις οποίες όμως και πάλι τις είδαμε στην απλή τους μορφή, δηλαδή διανύσματα και πίνακες από στοιχεία απλών τύπων 2. Η διεύθυνση της μνήμης στην οποία βρίσκονται τα δεδομένα στα οποία αναφέρεται η μεταβλητή δεν μας ενδιέφερε Το ερώτημα είναι τι πρέπει να χρησιμοποιήσουμε εάν θελήσουμε να αναφερθούμε σε θέσεις μνήμης αντί να αναφερθούμε απλά σε δεδομένα. Είναι προφανές ότι πρέπει να χρησιμοποιήσουμε πάλι κάποιο είδος μεταβλητής (άλλωστε όπως έχουμε δει το πρόγραμμα δουλεύει με μεταβλητές). Όμως αυτές οι μεταβλητές δεν παίρνουν τιμές ανάλογα με τον τύπο τους όπως οι άλλες οι «συνηθισμένες» μεταβλητές. Οι τιμές αυτών των «ειδικών» μεταβλητών είναι πάντα διευθύνσεις θέσεων μνήμης. Θα μπορούσαμε να πούμε ότι οι τιμές αυτές είναι σαν κάποιοι ειδικοί ακέραιοι αριθμοί που αναφέρονται σε θέσεις μνήμης του Η/Υ μας. Αυτές οι μεταβλητές που οι τιμές τους είναι θέσεις μνήμης του Η/Υ ονομάζονται δείκτες διεύθυνσης (pointers) Είναι επίσης προφανές ότι χρειαζόμαστε κάποιο τρόπο να ξεχωρίσουμε τις δηλώσεις των «απλών» μεταβλητών, από τις δηλώσεις αυτών των «ειδικών» μεταβλητών 11

Δείκτες διεύθυνσης (pointers) Πριν όμως προχωρήσουμε ας δούμε τι αντιπροσωπεύουν οι δείκτες διεύθυνσης. Στους περισσότερους μοντέρνους υπολογιστές η μνήμη τυχαίας προσπέλασης (RAM) είναι κατανεμημένη σε «κελιά» μήκους μιας ψηφιολέξης (byte), καθένα από τα οποία συνήθως μπορεί να αποθηκεύσει 8 bits. Δηλαδή ένας Η/Υ με 4GΒ RAM, έχει περίπου 4 δισεκατομμύρια bytes. Κάθε byte έχει μία μοναδική διεύθυνση ώστε να ξεχωρίζει από κάθε άλλο byte της μνήμης. Εάν υποθέσουμε ότι η μνήμη έχει μέγεθος κ bytes τότε οι διευθύνσεις είναι αριθμοί από το 0 μέχρι το (κ-1). 12

Παράδειγμα Διεύθυνση Περιεχόμενο 0 1 01010011 01101101 2 3 4... rate p_rate 11100101... Η p_rate είναι μια μεταβλητή που περιέχει τη θέση που είναι αποθηκευμένη η rate στη μνήμη. Δηλαδή, δείχνει στην rate ή είναι δείκτης της rate. κ-1 01110010 Για να γίνει αυτό θα πρέπει να αποθηκεύσουμε τη διεύθυνση της μεταβλητής rate στη μεταβλητή p_rate. 13

Παράδειγμα x Εάν υποθέσουμε ότι η μεταβλητή x είναι τύπου int, που απαιτεί 4 bytes, τότε η διεύθυνσή της είναι η διεύθυνση του πρώτου byte της. Η τιμή της x είναι 2 (10) (δηλ. στο δυαδικό: 00 00010) 32bits 2000 2001 2002 00000000 00000000 00000000 2003 00000010 14

Δήλωση δεικτών διεύθυνσης Είπαμε προηγουμένως ότι χρειαζόμαστε κάποιο τρόπο να ξεχωρίσουμε τις δηλώσεις των «απλών» μεταβλητών, από τις δηλώσεις αυτών των «ειδικών» μεταβλητών που ονομάζονται δείκτες διεύθυνσης (pointers). Ένας δείκτης διεύθυνσης πρέπει να δηλωθεί πριν χρησιμοποιηθεί. Η εντολή που δηλώνει μια μεταβλητή σαν δείκτη διεύθυνσης είναι: <τύπος> * <όνομα μεταβλητής> ; π.χ.: int * ptr_var; Ο αστερίσκος είναι ο τελεστής έμμεσης διευθυνσιοδότησης (ή τελεστής έμμεσης αναφοράς) και δηλώνει ότι ο ptr_var είναι ένας δείκτης σε int και όχι μία μεταβλητή τύπου ακέραιου. O μεταγλωττιστής δεν τον μπερδεύει με τον τελεστή του πολλαπλασιασμού! 15

Παράδειγμα int a_var; int * ptr_var; Δηλώνει μία «απλή» μεταβλητή με όνομα a_var Δηλώνει μία «ειδική» μεταβλητή δείκτη διεύθυνσης (pointer) με όνομα ptr_var Τι όμως σημαίνει η δήλωση για την ptr_var?;? Σημαίνει μία μεταβλητή : 1. στην οποία μπορούμε να αναφερθούμε στο πρόγραμμά μας με το συμβολικό όνομα ptr_var, 2. η μεταβλητή αυτή παίρνει τιμές που είναι διευθύνσεις μνήμης, και 3. αυτές οι διευθύνσεις μνήμης πρέπει να αποθηκεύουν δεδομένα που είναι τύπου int 16

Δείκτες - Σχηματικά int i, * p; p = &i; Διεύθυνση : 4000 p Διεύθυνση : 2000 i Εδώ η p είναι μεταβλητή τύπου δείκτη διεύθυνσης και η τιμή της είναι μια διεύθυνση, η διεύθυνση 2000, (στη προκειμένη περίπτωση η διεύθυνση αυτή περιέχει τα δεδομένα της μεταβλητής i). Προφανώς και η μεταβλητή δείκτη p έχει και αυτή μία διεύθυνση!! Στις περισσότερες περιπτώσεις όμως δεν μας ενδιαφέρει αυτή η διεύθυνση της μεταβλητής δείκτη. Απλά ας σκεφτούμε ότι μπορούμε να έχουμε μεταβλητές δείκτη σε δείκτες. Ευτυχώς σπάνια θα χρειαστούμε κάτι τέτοιο. 17

Παράδειγμα int *p; /* Δείκτης μόνο σε μεταβλητή τύπου int */ float *q ; /* Δείκτης μόνο σε μεταβλητή τύπου float */ char *r ; /* Δείκτης μόνο σε μεταβλητή τύπου char */ char *ch1, *ch2 ; float *value, *percent; Μπορούν να δηλωθούν μεταβλητές τύπου δείκτη διεύθυνσης σε οποιοδήποτε τύπο δεδομένων. Το σύμβολο * χρησιμοποιείται είτε ως τελεστής έμμεσης αναφοράς είτε ως τελεστής γινομένου. Ο μεταγλωττιστής μπορεί να τους διαχωρίζει από τα συμφραζόμενα. 18

Τελεστές σχετικοί με δείκτες Έχουμε δύο τελεστές σχετικούς με δείκτες: 1. Τελεστής διεύθυνσης (address operator) & 2. Τελεστής έμμεσης διευθυνσιοδότησης (ή αναφοράς) (indirection) * 19

Τελεστής διεύθυνσης (&) Όταν δηλώνουμε μία μεταβλητή δείκτη το μόνο που κάνουμε είναι να κρατάμε μνήμη αρκετά μεγάλη για την τιμή της μεταβλητής δείκτη (όχι την τιμή της μεταβλητής που «δείχνει» η μεταβλητή δείκτη). Στην αρχή η μεταβλητή δείκτη δεν έχει καμία τιμή (όπως άλλωστε θα περιμέναμε και από κάθε άλλη δήλωση μεταβλητής χωρίς αρχική τιμή). Ένας τρόπος να θέσουμε μία αρχική τιμή σε μία μεταβλητή δείκτη είναι να δώσουμε τη διεύθυνση μιας μεταβλητής του προγράμματος. 20

Τελεστής διεύθυνσης (&) Ένας τρόπος να θέσουμε μία αρχική τιμή σε μία μεταβλητή δείκτη διεύθυνσης είναι να της δώσουμε τη διεύθυνση μιας μεταβλητής του προγράμματος. Η διεύθυνση μιας μεταβλητής ενός προγράμματος υπολογίζεται από το τελεστή διεύθυνσης & Δηλαδή εάν: int i; Τότε &i επιστρέφει τη διεύθυνση της μεταβλητής i Οπότε εάν έχουμε τις δηλώσεις: int *p; int i; Μπορούμε να αποθέσουμε τη διεύθυνση της μεταβλητής i, στη μεταβλητή p ως εξής: p = &i; 21

Τελεστής έμμεσης αναφοράς (*) Αντίστροφα με τον τελεστή διεύθυνσης &, ο τελεστής έμμεσης διευθυνσιοδότησης *, επιστρέφει την τιμή των δεδομένων που βρίσκονται σε μια θέση μνήμης. Οπότε εάν: int *p, y = 0, i = 10; p = &i; /* Καταχωρώ τη διεύθυνση της i στη p άρα *p είναι η τιμή της i */ y = *p; printf("%d", i); /* Ισοδύναμες προτάσεις στη C */ printf("%d", *p); printf("%d", &i); /* Ισοδύναμες προτάσεις στη C */ printf("%d", p); Η έκφραση *p επιστρέφει τη τιμή που βρίσκεται στη θέση μνήμης που η μεταβλητή δείκτη διεύθυνσης p «δείχνει» (δηλαδή η έκφραση *p επιστρέφει τη τιμή 10, ενώ η p επιστρέφει την διεύθυνση της i (δηλαδή &i). 22

Δείκτες διεύθυνσης και τύποι μεταβλητών Η διεύθυνση μιας μεταβλητής είναι πραγματικά η διεύθυνση του πρώτου byte (χαμηλότερου) που καταλαμβάνει. Στην πραγματικότητα, ο μεταγλωττιστής της C αποθηκεύει μεταβλητές σε γειτονικές θέσεις μνήμης ανάλογα με τα πόσα bytes καταλαμβάνει η κάθε μεταβλητή. 23

Δείκτες διεύθυνσης και scanf Εάν ανατρέξουμε στη χρήση της scanf θα προσέξουμε ότι χρησιμοποιούσαμε το τελεστή διεύθυνσης! π.χ. scanf("%d", &i); Σ αυτή την περίπτωση, η συνάρτηση scanf λαμβάνει ως δεύτερο όρισμα ένα δείκτη (ουσιαστικά τη διεύθυνση της μεταβλητής που θέλουμε να της αποδώσουμε τιμή συγκεκριμένα εδώ την διεύθυνση της μεταβλητής i). Τι γίνεται όμως εάν η μεταβλητή π.χ. (i) είναι δείκτης? H scanf θα διαβάσει το δεδομένο και (δυστυχώς) χωρίς προειδοποίηση θα το αποθέσει ως τιμή του δείκτη. Γενικά όταν χρησιμοποιούμε δείκτες σαν παραμέτρους θα πρέπει να είμαστε σίγουροι ότι τα ορίσματα είναι διευθύνσεις και όχι οποιαδήποτε ακέραια τιμή. Η χρήση των πρωτότυπων μας επιτρέπει να είμαστε σίγουροι ότι ο μεταφραστής θα καταλάβει τέτοιου είδους λάθη στις περισσότερες περιπτώσεις. 24

Σύνοψη Εάν έχετε έναν δείκτη διεύθυνσης με όνομα ptr που έχει δεχθεί αρχική τιμή τη διεύθυνση της μεταβλητής var ισχύουν τα εξής: Τα *ptr και var αναφέρονται και τα δύο στα περιεχόμενα της var (οποιαδήποτε τιμή έχει αποθηκεύσει εκεί το πρόγραμμα). Τα ptr και &var αναφέρονται στη διεύθυνση της var. Ένα όνομα δείκτη χωρίς τον τελεστή * προσπελαύνει στην τιμή του δείκτη που είναι η διεύθυνση της μεταβλητής στην οποία δείχνει. Μελετήστε τους δείκτες, είναι πολύ σημαντικοί. Μη χρησιμοποιείτε έναν δείκτη που δεν έχει αρχική τιμή. Αν χρησιμοποιήσω τον τελεστή & σε ένα δείκτη θα πάρω τη διεύθυνση του δείκτη. 25