Προγραμματισμός Ι (HY20) # μνήμη & μεταβλητές πρόγραμμα & εκτέλεση
Ψηφιακά δεδομένα, μνήμη, μεταβλητές 2
Δυαδικός κόσμος Οι υπολογιστές είναι δυαδικές μηχανές Όλη η πληροφορία (δεδομένα και κώδικας) κωδικοποιείται ως μια ακολουθία από 0 ή Η ελάχιστη μονάδα πληροφορίας ονομάζεται bit bit μπορεί να πάρει τις τιμές 0 / Η βασική μονάδα πληροφορίας είναι το bte bte αποτελείται από 8 bit 3
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4
Μνήμη Αφαίρεση: μια (μακριά) σειρά από btes Πως γίνεται αναφορά σε ένα συγκεκριμένο bte; Διεύθυνση μας λέει το πού βρίσκεται ένα bte στην μνήμη συγκεκριμένα: ο αριθμός σειράς του bte στη μνήμη Οι διευθύνσεις αρχίζουν (θεωρητικά) από την τιμή 0
διευθύνσεις περιεχόμενα 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0... Ν-2 0 0 0 0 0 0 0 0 Ν- 0 0 0 0 6
Μνήμη ενός τυπικού υπολογιστή Κύρια μνήμη (RAM) γρήγορη πρόσβαση μερικά GB Σκληρός δίσκος (hard disk) αργή πρόσβαση λίγα TB KB = 024 B = 20 B MB = 024 KB = 220 B GB = 024 MB = 230 B TΒ = 024 GΒ = 240 B 7
Πρόσβαση στην μνήμη Λειτουργίες: ανάγνωση / εγγραφή Σημείο αναφοράς: διεύθυνση Ποσότητα δεδομένων: αριθμός btes Ανάγνωση: επιστρέφει τις τιμές των btes που έχουν αποθηκευτεί στις αντίστοιχες θέσεις Εγγραφή: προσδιορίζει τις τιμές των btes που θα αποθηκευτούν στις αντίστοιχες θέσεις 8
Ανάγνωση διεύθυνση op=read adr=3 len= 000 μηχανισμός πρόσβασης μνήμης περιεχόμενα 0 0 0 0 0 0 0 0 2 0 0 3 0 0 0 4 0 0 0 0 0 0... 9 Ν- 0 0 0 0 0 0 Ν 0 0 0
Εγγραφή διεύθυνση op=write adr= len=2 00000 000 μηχανισμός πρόσβασης μνήμης Η/Υ περιεχόμενα 0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0 0 0 0... 0 Ν- 0 0 0 0 0 0 Ν 0 0 0
Κωδικοποίηση δεδομένων Κωδικοποίηση: η μετατροπή δεδομένων από ένα σύστημα αναπαράστασης σε ένα άλλο δεκαδικό -> δυαδικό χαρακτήρες -> δυαδικό,... Πόσα bits χρειαζόμαστε για κάθε είδος δεδομένων; Περισσότερα bits/btes μεγαλύτερο πεδίο τιμών μεγαλύτερη ακρίβεια Με Ν bits κωδικοποιούμε 2Ν διαφορετικές τιμές π.χ. πεδίο φυσικών [0...2Ν-] π.χ. πεδίο ακεραίων [-2Ν-...2Ν--]
Δεδομένα και πρόγραμματισμός Για κάθε δεδομένο πρέπει να καθοριστεί (από τον προγραμματιστή) η θέση μνήμης για την αποθήκευση του ο αριθμός των btes που χρειάζονται για την αποθήκευση των τιμών που μπορεί να λάβει η κωδικοποίηση που χρησιμοποιείται για κάθε τιμή στο δυαδικό σύστημα Απάνθρωπο! Χρειάζεται κατάλληλη υποστήριξη από τις γλώσσες προγραμματισμού... 2
Τύποι δεδομένων Κάθε γλώσσα προγραμματισμού ορίζει ένα σύνολο από βασικούς τύπους δεδομένων Κάθε βασικός τύπος έχει προκαθορισμένο μέγεθος (σε btes) συγκεκριμένη δυαδική κωδικοποίηση και αντίστοιχο πεδίο τιμών Ο προγραμματιστής ορίζει κάθε δεδομένο του προγράμματος ως αντικείμενο ενός τύπου καθορίζει έμμεσα το μέγεθος και την κωδικοποίηση του (την σημασία των bits που αντιστοιχούν στο αντικείμενο) Η μνήμη αποθηκεύει τις τιμές των bits/btes χωρίς να γνωρίζει το πως αυτές ερμηνεύονται 3
Αναφορά σε αντικείμενα δεδομένων Σε κάθε αντικείμενο δεδομένων του προγράμματος δίνεται και ένα μνημονικό όνομα Το όνομα μπορεί να χρησιμοποιείται, αντί της διεύθυνσης, στις πράξεις ανάγνωσης/αλλαγής των τιμών του αντικειμένου Η πρόσβαση στην μνήμη εξακολουθεί να γίνεται με βάση την θέση μνήμης και τον αριθμό btes προς ανάγνωση/αποθήκευση η αντιστοίχιση γίνεται αυτόματα από την γλώσσα προγραμματισμού 4
Μεταβλητή Αντικείμενο δεδομένων του προγράμματος με συγκεκριμένο όνομα και τύπο «Διαβάζουμε» μια μεταβλητή διαβάζουμε την τιμή που έχει αποθηκευτεί στην αντίστοιχη θέση της μνήμης «Αναθέτουμε» μια τιμή σε μεταβλητή γράφουμε την τιμή στην αντίστοιχη θέση της μνήμης «Δέσμευση» μεταβλητής δέσμευση αντίστοιχου χώρου στην μνήμη «Ζωή» μεταβλητής διάστημα κατά το οποίο ο χώρος παραμένει δεσμευμένος
int var; θεση/διεύθυνση: τύπος: int διεύθυνση τύπος int μέγεθος: 2 btes ερμηνεία: ακέραιος κωδικοποίηση: 2 s complement τι τιμή έχει η μεταβλητή var; διάβασε από τη διεύθυνση της var όσα btes ορίζει ο τύπος της T (π.χ. int), και ερμήνευσέ τα σύμφωνα με τη σύμβαση κωδικοποίησης του T περιεχόμενα 0 0 0 0 0 2 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0... Ν- 0 0 0 0 0 0 Ν 0 0 0 αποτέλεσμα = 2 (για little-endian) 6
Little-endian vs. big-endian Little-endian: η σημαντικότητα των btes αυξάνει όσο μεγαλώνουν οι διευθύνσεις το λιγότερο σημαντικό bte είναι στην μικρότερη διεύθυνση Big-endian: η σημαντικότητα των btes μειώνεται όσο μεγαλώνουν οι διευθύνσεις το πιο σημαντικό bte είναι στην μικρότερη διεύθυνση ακέραιος που καταλαμβάνει 2 btes, αρχίζοντας από την διεύθυνση k και έχει την τιμή 2 διευθύνσεις little-endian big-endian k k+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7
Διαφάνεια αποθήκευσης/κωδικοποίησης Ο προγραμματιστής δεν χρειάζεται να γνωρίζει το πώς ακριβώς αποθηκεύεται/κωδικοποιείται η πληροφορία στην μνήμη του υπολογιστή Η προσπέλαση των περιεχομένων των μεταβλητών του προγράμματος γίνεται με διαφανή τρόπο ένα από τα πλεονεκτήματα του να χρησιμοποιεί κανείς μια γλώσσα προγραμματισμού υψηλού επιπέδου Ο προγραμματιστής δεν καταλαβαίνει τη διαφορά όσο χρησιμοποιεί κανονικές πράξεις πρόσβασης Αυτό αλλάζει όταν χρησιμοποιείται γλώσσα μηχανής ή/και προσπελάζονται τα δεδομένα που βρίσκονται στη μνήμη με άμεσο τρόπο βλέπε αργότερα... 8
Πρόγραμμα & εκτέλεση 9
Πρόγραμμα / Γλώσσα προγραμματισμού Πρόγραμμα: εντολές γραμμένες σε μια συγκεκριμένη γλώσσα προγραμματισμού αυτή που «καταλαβαίνει» ο υπολογιστής με λίγη βοήθεια (ο υπολογιστής ξέρει μόνο από 0 και ) Γλώσσα προγραμματισμού: γλώσσα σχεδιασμένη για να δίνουμε εντολές στον υπολογιστή Σαν τις κανονικές γλώσσες, αλλά πολύ πιο τυπική περιορισμένο λεξιλόγιο σαφής σημασιολογία ξεκάθαρο συντακτικό 20
Συντακτικό Το συντακτικό ορίζει το σύνολο των επιτρεπτών προτάσεων (ακολουθία συμβόλων) Επιτρεπτή πρόταση = συντακτικά ορθό πρόγραμμα μπορεί να μεταφραστεί σε γλώσσα μηχανής και να εκτελεστεί στον υπολογιστή Ειδικές «γλώσσες» περιγραφής των κανόνων σύνταξης γλωσσών προγραμματισμού Etended Backus Naur Form (EBNF) συντακτικά διαγράμματα 2
Σύνταξη & σημασία Σύνταξη: κανόνες για τον σχηματισμό προτάσεων Σημασία: το νόημα που έχουν οι συντακτικά επιτρεπτές προτάσεις η σύνταξη μιας γλώσσας δεν μπορεί να ορίσει ταυτόχρονα και την σημασία της Υπάρχουν συντακτικά επιτρεπτές προτάσεις που δεν έχουν ορισμένη (μια μοναδική) σημασία; Στις ανθρώπινες γλώσσες: ναι! μαζί μιλάμε και χώρια καταλαβαινόμαστε Σε γλώσσες προγραμματισμού: (κατά κανόνα) όχι 22
Για παράδειγμα Συντακτικά ορθές προτάσεις -2+3 /-2 Όμως, σε τι τιμές αντιστοιχούν τα παρακάτω; -2+ (-2)+(3) ή (2+3) /- (/)-2 ή /(-2) 23
Μεταγλώττιση Κώδικας: μια σειρά εντολών προς τον υπολογιστή, γραμμένες με βάση μια γλώσσα προγραμματισμού Μεταγλώττιση: διαδικασία μετατροπής κώδικα από μια γλώσσα σε μια άλλη συνήθως από εντολές υψηλού επιπέδου σε εντολές μηχανής μια εντολή γλώσσας υψηλού επιπέδου μπορεί να αντιστοιχεί σε μια σειρά εντολών γλώσσας μηχανής Γίνεται από ειδικά προγράμματα, τους λεγόμενους μεταγλωττιστές (compilers) Η μεταγλώττιση γίνεται (συνήθως) ως ξεχωριστή διαδικασία, πολύ πριν αρχίσει η εκτέλεση του κώδικα υπάρχουν περιπτώσεις όπου η μετάφραση γίνεται ακριβώς πριν αρχίσει η εκτέλεση (just in time compilation) 24
εντολές γλώσσας compiler γλώσσα -> 00000 εντολές μηχανής CPU 2
Συμβάσεις εκτέλεσης Κάθε γλώσσα έχει συγκεκριμένες συμβάσεις για την αποτίμηση και εκτέλεση των εκφράσεων/προτάσεων Συνήθως «από αριστερά προς τα δεξιά» και «από πάνω προς τα κάτω» όπως γράφουμε/διαβάζουμε κείμενα (στον δυτικό κόσμο) Επίσης, μπορεί να γίνουν άλματα μέσα στον κώδικα είτε «προς τα εμπρός» είτε «προς τα πίσω» κάποιες εντολές μπορεί να παρακαμφθούν ή/και να εκτελεστούν παραπάνω από μια φορά Πραγματοποιούνται με ειδικές εντολές της γλώσσας εντολές ελέγχου ροής εκτέλεσης προγράμματος εντολές κλήσης υποπρογραμμάτων 29
Έλεγχος ροής εκτέλεσης Ο προγραμματιστής μπορεί να επηρεάσει την ροή εκτέλεσης του προγράμματος Mέσω εντολών ελέγχου Διαβάζουν την κατάσταση του προγράμματος και ανάλογα μπορεί να μεταφέρουν την εκτέλεση σε ένα διαφορετικό σημείο του κώδικα Μπορούμε να φτιάξουμε προγράμματα με εντολές που εκτελούνται υπό συνθήκη / επανειλημμένα 30
Εκτέλεση προγράμματος γράψιμο αρχικοποίηση κατάστασης διάβασμα εκτέλεση επόμενης εντολής μεταβλητές γράψιμο μνήμη επιλογή επόμενης εντολής 3
: : <- - 32
εκτέλεση P(0,) s?? : :?? <- - 33
εκτέλεση P(0,) s?? : : 0 <- - 34
εκτέλεση P(0,) s? : : 0 <- - 3
εκτέλεση P(0,) s? : : <- - 36 0
εκτέλεση P(0,) s 0 : : <- - 37 0
εκτέλεση P(0,) s 0 2 : : <- - 38 0
εκτέλεση P(0,) s 0 2 : : <- - 39 0
εκτέλεση P(0,) s 0 2 : : <- - 40 0
εκτέλεση P(0,) s 0 6 : : <- - 4 0
εκτέλεση P(0,) s 0 6 : : <- - 42 0
εκτέλεση P(2,) s?? : :?? <- - 43
εκτέλεση P(2,) s?? : : 2 <- - 44
εκτέλεση P(2,) s?? : : 2 <- - 4
εκτέλεση P(2,) s? : : 2 <- - 46
εκτέλεση P(2,) s? : : <- - 47 2
εκτέλεση P(2,) s 0 : : <- - 48 2
εκτέλεση P(2,) s 0 2 : : <- - 49 2
εκτέλεση P(2,) s 0 2 : : <- - 0 2
εκτέλεση P(2,) s 0 2 : : <- - 2
εκτέλεση P(2,) s 0 3 : : <- - 2 2
εκτέλεση P(2,) s 0 3 : : <- - 3 2
εκτέλεση P(2,) s 0 3 : : <- - 4 2
εκτέλεση P(2,) s 3 : : <- - 2
εκτέλεση P(2,) s 4 : : <- - 6 2
εκτέλεση P(2,) s 4 : : <- - <- - 7 2
εκτέλεση P(2,) s 4 : : <- - <- - 8 2
εκτέλεση P(2,) s 4 : : <- - <- - 9
εκτέλεση P(2,) s : : <- - <- - 60
εκτέλεση P(2,) s : : <- - <- - 6
εκτέλεση P(2,) s 2 : : <- - <- - 62
εκτέλεση P(2,) s 2 : : if ( is s <- s + <- if ( is <- - 63 0) goto 6 0) goto 6
εκτέλεση P(2,) s 2 : : if ( is s <- s + <- if ( is <- - 64 0) goto 6 0) goto 6
εκτέλεση P(2,) s 3 : : if ( is s <- s + <- if ( is <- - 6 0) goto 6 0) goto 6
εκτέλεση P(2,) s 3 : : if ( is s <- s + <- if ( is s <- s + <- - 66 0) goto 6 0) goto 6
εκτέλεση P(2,) s 3 : : if ( is s <- s + <- if ( is s <- s + <- - 67 0) goto 6 0) goto 6
εκτέλεση P(2,) s 0 : : if ( is s <- s + <- if ( is s <- s + <- - 68 3 0) goto 6 0) goto 6
εκτέλεση P(2,) s 0 : : if ( is s <- s + <- if ( is s <- s + <- - 69 4 0) goto 6 0) goto 6
εκτέλεση P(2,) s 0 : : if ( is s <- s + <- if ( is s <- s + <- - <- - 70 4 0) goto 6 0) goto 6
εκτέλεση P(2,) s 0 : : if ( is s <- s + <- if ( is s <- s + <- - <- - 7 4 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- - <- - 72 4 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- - <- - 73 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 74 0) goto 6 0) goto 6 )
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 7 2 0) goto 6 0) goto 6 )
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 76 2 0) goto 6 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 77 2 0) goto 6 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 78 6 0) goto 6 0) goto 6 0) goto 6
εκτέλεση P(2,) 0 s 0 : : if ( is s <- s + <- if ( is s <- s + <- if ( is <- - 79 6 0) goto 6 0) goto 6 0) goto 6
Υποπρογράμματα Ομάδα εντολών (και δεδομένων) που είναι συντακτικά ή/και εκτελεστικά ανεξάρτητη (αυτόνομη) από τον υπόλοιπο κώδικα ένα πρόγραμμα μπορεί να αποτελείται από (ή να χρησιμοποιεί) πολλά διαφορετικά υποπρογράμματα Όταν καλείται ένα υποπρόγραμμα, η εκτέλεση μεταφέρεται στο υποπρόγραμμα Όταν τερματιστεί η εκτέλεση του, επιστρέφει πίσω στο πρόγραμμα που πραγματοποίησε την κλήση Η χρήση υποπρογραμμάτων αποτελεί μια από τις βασικές αρχές δομημένου προγραμματισμού πολύ σημαντικό στην πράξη 80
πρόγραμμα P code A call P2 code B εκτέλεση P code A call P2 call P3 code D return code C return code B πρόγραμμα P2 call P3 code C return πρόγραμμα P3 code D return 8
Μεθοδολογία επίλυσης προβλημάτων Ανάλυση του προβλήματος τι δεδομένα έχουμε στην διάθεση μας; τι θέλουμε να βρούμε; πώς σπάει σε μικρότερα / απλούστερα προβλήματα; ποια στρατηγική πρέπει να ακολουθήσουμε; Σχεδιασμός αλγορίθμου ακριβής ακολουθία πεπερασμένων βημάτων που πρέπει να ακολουθηθούν για να λυθεί το πρόβλημα Απαιτήσεις ορθότητα, καλή επίδοση, εξοικομόμηση πόρων Για το ίδιο πρόβλημα πιθανόν να υπάρχουν περισσότεροι κατάλληλοι αλγόριθμοι 82
Παράδειγμα: γραμμική αναζήτηση Βρες τη θέση που υπάρχει (αν υπάρχει) η τιμή 0 ο βήμα 3 7 20 2 34 4 46 47 0 9 6 63 70 2ο βήμα 3 7 20 2 34 4 46 47 0 9 6 63 70 3ο βήμα 3 7 20 2 34 4 46 47 0 9 6 63 70 0ο βήμα 3 7 20 2 34 4 46 47 0 9 6 63 70 83
Παράδειγμα: δυαδική αναζήτηση Βρες τη θέση που υπάρχει (αν υπάρχει) η τιμή 0 ο βήμα 3 7 20 2 34 4 46 47 0 9 6 63 70 μέσο κάτω όριο 2ο βήμα πάνω όριο 3 7 20 2 34 4 46 47 0 9 6 63 70 μέσο κάτω όριο 3ο βήμα πάνω όριο 3 7 20 2 34 4 46 47 0 9 6 63 70 κάτω όριο 84 μέσο πάνω όριο
Αποσφαλμάτωση (debugging) Συντακτικό επίπεδο (εύκολο) ο κώδικας δεν αντιστοιχεί σε συντακτικά επιτρεπτή πρόταση ευκολάκι, νά' ναι καλά αυτός που έγραψε τον compiler Σημασιολογικό επίπεδο (δύσκολο) ο κώδικας είναι συντακτικά σωστός και εκτελείται (τρέχει) αλλά εμείς δεν χρησιμοποιούμε σωστά κάποια εντολή άλλο θέλουμε να κάνουμε και άλλο ζητάμε από τον υπολογιστή να κάνει: παράγεται λάθος αποτέλεσμα επίπονο, αλλά η κατάσταση βελτιώνεται με την εμπειρία Λογικό επίπεδο (πιο δύσκολο) ο κώδικας είναι συντακτικά και σημασιολογικά σωστός υπάρχει λάθος σε επίπεδο αλγορίθμου (σκέψης) το πιο δύσκολο, ακόμα και για πολύ έμπειρους 87
Αποσφαλμάτωση (debugging) στο παρελθόν 88
Χρονικό σημείο εντοπισμού λαθών Χρόνος μετάφρασης (compile time) ο εντοπισμός λαθών γίνεται από τον μεταγλωττιστή, αναλόγως με την γλώσσα προγραμματισμού π.χ. συντακτικά λάθη, λάθη ανάθεσης τιμών,... Χρόνος εκτέλεσης (run time / eecution time) ο εντοπισμός λαθών γίνεται από το περιβάλλον εκτέλεσης (λειτουργικό ή ακόμα και τον ίδιο τον επεξεργαστή) π.χ. προσπέλαση άκυρων διευθύνσεων, αριθμητικά λάθη,... Μετά την εκτέλεση ο εντοπισμός λαθών γίνεται από τον χρήστη ή ένα άλλο πρόγραμμα με βάση τα αποτελέσματα που παράγει το πρόγραμμα, χωρίς αυτό να έχει παρουσιάσει κάποιο «ορατό» λάθος 89
Ορθότητα (correctness) Ορθότητα: ο κώδικας υλοποιεί την επιθυμητή (προδιαγεγραμμένη) λειτουργικότητα για όλες τις δυνατές περιπτώσεις Το γεγονός ότι ο κώδικας μεταφράστηκε επιτυχώς (προφανώς) δεν συνεπάγεται ορθότητα Το γεγονός ότι ο μεταγλωττισμένος κώδικας εκελείται (τρέχει) δεν συνεπάγεται ορθότητα Το πρόγραμμα πάλι μπορεί να μην λειτουργεί σωστά να μην κάνει αυτό που θέλουμε, σε όλες τις περιπτώσεις Η εκτέλεση αυτή καθ αυτή γίνεται πάντα σωστά όπως ορίζεται από την σημασιολογία της γλώσσας προγραμματισμού δεν φταίει το «καταραμένο μηχάνημα» μπορεί να υπάρχουν σημασιολογικά ή/και λογικά λάθη 94
Ο νέος = ψάρι = γατάκι Ο παλιός 9