Κυριακή 4 Μαρτίου 2012

Δομημένος Προγραμματισμός Η/Υ σε C: Εργαστήριο 3 - Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (3)

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ ΣΕ C
ΕΡΓΑΣΤΗΡΙO 3

Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (3)
ΠΕΡΙΕΧΟΜΕΝΑ







  • 9. Δημιουργία τυχαίων αριθμητικών τιμών με srand() και rand(). Δημιουργία τυχαίων αλφαριθμητικών τύπου ASCII και λεξικογραφική σύγκρισή τους με strcmp(). Προαιρετική συνένωσή τους από τον χρήστη με strcat().











  • 10. Διαδικαστική υλοποίηση των εξής σειριακών αλγορίθμων: ταξινόμηση φυσαλίδας, quicksort και δυαδική αναζήτηση. Εφαρμογή σε τυχαίως αρχικοποιημένα αριθμητικά δεδομένα, αποθηκευμένα σε πίνακα.











  • 11. Αξιοποίηση έτοιμων συναρτήσεων βιβλιοθήκης qsort() και bsearch() για τη λεξικογραφική ταξινόμηση τυχαίων αλφαριθμητικών.











  • 12. Υλοποίηση του αφελούς αλγορίθμου αναζήτησης υποσυμβολοσειρών σε αλφαριθμητικά, για είσοδο από αρχείο κειμένου τυχαία αρχικοποιημένο.









  • <Β>ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ C ΔΟΜΗΜΕΝΟΣ STRUCTURED PROGRAMMING PROCEDURAL C++ ΔΙΑΔΙΚΑΣΙΕΣ ΣΥΝΑΡΤΗΣΕΙΣ PROCEDURES FUNCTIONS


    Δομημένος Προγραμματισμός Η/Υ σε C: Εργαστήριο 2 - Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (2)

    ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ ΣΕ C
    ΕΡΓΑΣΤΗΡΙO 2

    Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (2)
    ΠΕΡΙΕΧΟΜΕΝΑ






  • 5. Δυναμική δέσμευση μονοδιάστατου πίνακα με malloc() και αποθήκευση αλφαριθμητικού σε αυτόν.








  • 6. Δυναμική δέσμευση δισδιάστατου πίνακα και αποθήκευση πολλαπλών αλφαριθμητικών σε αυτόν.








  • 7. Δημιουργία και κλήση συνάρτησης για έλεγχο εγκυρότητας ημερομηνίας, την οποία έχει εισαγάγει ο χρήστης από το πληκτρολόγιο (π.χ. ώστε 1 < ΜΗΝΑΣ < 12, κλπ). Πέρασμα παραμέτρων με τιμή, πέρασμα παραμέτρων με αναφορά.








  • 8. Επανυλοποίηση του παραδείγματος 3, με δυναμικά δεσμευόμενη συνδεδεμένη λίστα.






  • <Β>ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ C ΔΟΜΗΜΕΝΟΣ STRUCTURED PROGRAMMING PROCEDURAL C++ ΔΙΑΔΙΚΑΣΙΕΣ ΣΥΝΑΡΤΗΣΕΙΣ PROCEDURES FUNCTIONS

    Δευτέρα 14 Φεβρουαρίου 2011

    Δομημένος Προγραμματισμός Η/Υ σε C: Εργαστήριο 1 - Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (1)

    ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ ΣΕ C
    ΕΡΓΑΣΤΗΡΙO 1

    Εργαστηριακά Παραδείγματα Προγραμμάτων σε C (1)
    ΠΕΡΙΕΧΟΜΕΝΑ






  • 1. Υλοποίηση στοιχειώδους αριθμομηχανής, με επαναλαμβανόμενη είσοδο τελεστέων και επιλογή τελεστών από τον χρήστη.








  • 2. Αντικατάσταση συνήθους μεθόδου εισόδου  και αποθήκευσης αλφαριθμητικού [scanf(%s)],  με scanf(%c) ή getchar() σε βρόχο επανάληψης for, do ή while.








  • 3. Μέτρηση χαρακτήρων αλφαριθμητικού με επαναληπτικό βρόχο και μετρητή [αντικατάσταση της strlen()].








  • 4. Επαναληπτική εισαγωγή στοιχείων και αποθήκευση καταλόγου εγγραφών (με κάθε εγγραφή αποτελούμενη από όνομα, ηλικία και διεύθυνση) σε στατικό πίνακα διάστασης N x 2. Η δεύτερη στήλη περιέχει μία λογική σημαία εγκυρότητας της εγγραφής. Εξαγωγή σε αρχείο κειμένου, ανάγνωση από αρχείο.






  • <Β>ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ C ΔΟΜΗΜΕΝΟΣ STRUCTURED PROGRAMMING PROCEDURAL C++ ΔΙΑΔΙΚΑΣΙΕΣ ΣΥΝΑΡΤΗΣΕΙΣ PROCEDURES FUNCTIONS

    Κυριακή 13 Φεβρουαρίου 2011

    Λειτουργικά Συστήματα: Διάλεξη 5

    ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ
    ΘΕΩΡΙΑ


    5: Εικονική μνήμη, Συστήματα αρχείων, Είσοδος / Έξοδος
    • Διαχείριση μνήμης:
    oΟι σύγχρονοι επεξεργαστές έχουν καταχωρητές μεγέθους 32 bit ή 64 bit. Επειδή οι διευθύνσεις μνήμης που περιέχονται στον κώδικα των εκτελούμενων προγραμμάτων αποθηκεύονται σε αυτούς τους καταχωρητές κατά την εκτέλεση, πρέπει να χωρούν σε αυτούς, με αποτέλεσμα ένας 32μπιτος υπολογιστής να μπορεί να διευθυνσιοδοτήσει μέχρι 232 διαφορετικά byte μνήμης RAM (=4 GB).
    oΌμως ως τη δεκαετία του 2000 ελάχιστοι υπολογιστές είχαν τόση πολλή μνήμη, ενώ ακόμη και όσοι είχαν έπρεπε να τη διαμοιράζουν μεταξύ πολλαπλών εκτελούμενων διεργασιών σ' ένα πολυδιεργασιακό ΛΣ (συμπεριλαμβανομένων των διεργασιών συστήματος του πυρήνα).
    oΈτσι στις περισσότερες σύγχρονες αρχιτεκτονικές υπολογιστών εφαρμόζεται από τον πυρήνα, με υποστήριξη από το υλικό του επεξεργαστή, ένας μηχανισμός «εικονικής μνήμης» (virtual memory) -- συνήθως με τη μέθοδο της «σελιδοποίησης» (paging).


    • Σελιδοποίηση:
    oΚάθε διεργασία έχει στη διάθεσή της έναν πλήρη, ιδιωτικό χώρο εικονικών διευθύνσεων σταθερού μεγέθους (2 GB στα Windows, ενώ τα άλλα 2 GB δεσμεύονται για χρήση από το ΛΣ), στον οποίον έχει πρόσβαση μόνο αυτή και το ΛΣ. Συν τοις άλλοις έτσι διασφαλίζεται στοιχειώδης προστασία μεταξύ των διεργασιών, αφού η καθεμία δεν μπορεί να προσπελάσει τη μνήμη της άλλης.
    oΑυτός ο χώρος διευθύνσεων διαμερίζεται σε σελίδες επίσης σταθερού μεγέθους (συνήθως 4 ΚΒ), ενώ η φυσική μνήμη (η οποία μπορεί να είναι πολύ μικρότερη από τα εικονικά 2 GB που έχει κάθε διεργασία στη διάθεσή της) διαμερίζεται σε ίδιου μήκους πλαίσια σελίδων. Σε κάθε πλαίσιο σελίδων μπορεί κάθε στιγμή να είναι φορτωμένη μία σελίδα. Κάθε διεργασία περιέχει έναν πίνακα σελίδων (page table), με μία εγγραφή για κάθε εν χρήση σελίδα του εικονικού της χώρου διευθύνσεων, ο οποίος διατηρεί τις αντιστοιχίες μεταξύ σελίδων και πλαισίων σελίδων.
    oΜία σελίδα όμως μπορεί να μην είναι φορτωμένη πραγματικά στη RAM (π.χ. δεν χωράει αν η φυσική RAM είναι μικρότερη από τη μνήμη που απαιτούν συνολικά ο πυρήνας και οι εκτελούμενες εφαρμογές), αλλά να είναι αποθηκευμένη σε ένα ειδικό αρχείο του δίσκου, ονόματι αρχείο αντιμετάθεσης (swap file), που ελέγχεται και συντηρείται από τον πυρήνα. Σε αυτήν την περίπτωση η εγγραφή  που της αντιστοιχεί στον πίνακα σελίδων δεν περιέχει  καμία διεύθυνση πλαισίου, αλλά είναι σημειωμένη ως «απούσα».
    oΑν ο εκτελούμενος κώδικας επιχειρήσει να προσπελάσει εικονική διεύθυνση που περιέχεται σε απούσα σελίδα, τότε το υλικό παράγει ένα σφάλμα σελίδας (page fault) που το χειρίζεται αυτόματα το ΛΣ: μετακινεί τη ζητούμενη σελίδα από το αρχείο αντιμετάθεσης σε ένα πλαίσιο της RAM (αντικαθιστώντας πιθανώς μία άλλη σελίδα που μεταφέρεται τώρα στο αρχείο) και επιστρέφει τον έλεγχο στην εφαρμογή.
    oΜε τον μηχανισμό της εικονικής μνήμης:
    • Κάθε διεργασία έχει απεριόριστη πρόσβαση σε έναν μεγάλο, ιδιωτικό και προστατευμένο χώρο διευθύνσεων, στο εύρος 0 - 2 GB. Ο χώρος αυτός είναι εικονικός, αλλά την αντιστοίχιση με τη φυσική μνήμη την αναλαμβάνει διαφανώς το ΛΣ με τη βοήθεια του υλικού, κατά τον χρόνο εκτέλεσης της εφαρμογής.
    • Έτσι οι προγραμματιστές των εφαρμογών και των μεταγλωττιστών δεν χρειάζεται να ενδιαφέρονται για τις πραγματικές διευθύνσεις μνήμης τις οποίες θα καταλαμβάνει το λογισμικό χρήστη κάθε φορά που θα εκτελείται.
    • Ο δίσκος χρησιμοποιείται ως επέκταση της φυσικής RAM.


    • Translation Lookaside Buffer (TLB):
    oΟ TLB είναι μία κρυφή μνήμη (cache) στο υλικό της CPU (τελείως ανεξάρτητη από την κανονική κρυφή μνήμη), η οποία αντί να αποθηκεύει δεδομένα από την κύρια μνήμη για ταχύτερη προσπέλασή τους από τον επεξεργαστή, αποθηκεύει προσφάτως χρησιμοποιημένες αντιστοιχήσεις μεταξύ φυσικών και εικονικών διευθύνσεων μνήμης, δηλαδή εγγραφές από τους διάφορους πίνακες σελίδων όλων των ενεργών διεργασιών.
    oΈτσι επιταχύνεται η μετάφραση εικονικών σε φυσικές διευθύνσεις κατά τον χρόνο εκτέλεσης κάθε προγράμματος, αφού μειώνονται οι προσπελάσεις στη RAM (πολύ βραδύτερη από τον TLB), όπου είναι αποθηκευμένοι οι πίνακες σελίδων.
    oΕπομένως, μόνο αν η ζητούμενη αντιστοίχηση εικονικής σε φυσική διεύθυνση δεν βρεθεί στον TLB θα επιχειρηθεί ανάγνωσή της από τον πίνακα σελίδων. Μόλις ωστόσο η φυσική διεύθυνση μεταφερθεί από τη RAM στον επεξεργαστή, θα τοποθετηθεί και η ανάλογη εγγραφή στον TLB, ώστε την επόμενη φορά που θα ζητηθεί να μη χρειαστεί ξανά πρόσβαση στην κύρια μνήμη.


    • Αλγόριθμοι αντικατάστασης σελίδων:
    oΌταν συμβαίνει ένα σφάλμα σελίδας και μία σελίδα μνήμης μεταφέρεται από το αρχείο αντιμετάθεσης του δίσκου στη RAM, αλλά δεν υπάρχει ελεύθερο πλαίσιο σελίδας για την τοποθέτησή της (η φυσική μνήμη είναι πλήρης), τότε πρέπει μία υπάρχουσα σελίδα να μεταφερθεί στον δίσκο και η νέα να τοποθετηθεί στο πλαίσιο που απελευθερώνεται. Ο μηχανισμός ο οποίος αποφασίζει ποιες σελίδες θα εναλλαχθούν και υλοποιεί την απόφαση λέγεται επόπτης σελιδοποίησης.
    oΟ επόπτης σελιδοποίησης αξιοποιεί κάποιον αλγόριθμο αντικατάστασης σελίδων για να επιλέξει ποια σελίδα θα μετακινηθεί από τη RAM στο αρχείο αντιμετάθεσης. Συνήθως στον δίσκο μεταφέρεται η σελίδα που προσπελάστηκε λιγότερο πρόσφατα από όλες.


    • Σύστημα αρχείων (Filesystem):
    oΣύστημα αρχείων ονομάζεται ο μηχανισμός των λειτουργικών συστημάτων ο οποίος οργανώνει την αποθήκευση, προσπέλαση και διαχείριση αρχείων και καταλόγων στις μονάδες δίσκου του υπολογιστή. Συνήθως αποτελεί τμήμα του πυρήνα και συνίσταται σε κατάλληλο κώδικα, αλλά και σε δομές δεδομένων αποθηκευμένες στους ίδιους τους δίσκους.
    oΜία μονάδα δίσκου (δισκέτα, φλασάκι USB, σκληρός δίσκος, οπτικός δίσκος κλπ) διαιρείται από τη σκοπιά του υλικού σε μικρά τμήματα, στα οποία χωρά μία ελάχιστη ποσότητα δεδομένων. Ενδεικτικά, στους σκληρούς δίσκους και στις δισκέτες τα τμήματα αυτά ονομάζονται τομείς και συνήθως χαρακτηρίζονται από χωρητικότητα 512 byte, 1 Kb, 2 Kb ή 4 Kb το καθένα.
    oΑπό τη σκοπιά του συστήματος αρχείων, οι τομείς αυτοί ομαδοποιούνται σε «μπλοκ» (συνήθως των 4, 8, 16 ή 32 Kb το καθένα) και οι μηχανισμοί του ΛΣ είναι υπεύθυνοι για τη διατήρηση αντιστοιχήσεων μεταξύ αρχείων και των μπλοκ όπου διατηρούνται τα περιεχόμενα κάθε αρχείου. Οι πληροφορίες αυτές αποθηκεύονται στις δομές δεδομένων που καταλαμβάνει το σύστημα αρχείων στην εκάστοτε μονάδα δίσκου, δεσμεύοντας κάποιο ποσοστό της χωρητικότητάς της. Οι εν λόγω δομές δεδομένων είναι παντελώς αόρατες για τους τελικούς χρήστες και προσπελάσιμες μόνο από το ΛΣ.
    oΓια κάθε αρχείο αποθηκεύεται το όνομά του, κάποια συναφή μεταδεδομένα (π.χ. μέγεθος, ημερομηνία δημιουργίας, άδειες πρόσβασης από διαφορετικούς χρήστες κλπ), καθώς και μία λίστα με τα μπλοκ τα οποία καταλαμβάνουν τα περιεχόμενά του. Τα μπλοκ αυτά δεν είναι απαραιτήτως διαδοχικά και γι' αυτό ένα αρχείο μπορεί στην πραγματικότητα να είναι διασπασμένο σε πολλά τμήματα, τοποθετημένα σε διαφορετικά σημεία της μονάδας δίσκου. Για τους καταλόγους, αποθηκεύεται επιπροσθέτως και μία λίστα με τα αρχεία που περιέχουν (συμπεριλαμβανομένων υποκαταλόγων, καθώς ένας κατάλογος δεν είναι παρά ειδικός τύπος αρχείου).
    oΣε κάθε απόπειρα προσπέλασης αρχείου / καταλόγου από τον δίσκο, ο πυρήνας εντοπίζει και δίνει στο υλικό εντολές ανάγνωσης των κατάλληλων δεδομένων συμβουλευόμενος αρχικά τις δομές του συστήματος αρχείων. Η όλη διαδικασία είναι τελείως διαφανής για τον χρήστη.
    oΟ χρήστης μπορεί προαιρετικά να «διαμερίσει» (partition) μία μονάδα δίσκου σε κατατμήσεις διαφορετικού μεγέθους, αρκεί να έχει δικαίωμα εγγραφής σε αυτήν. Σε καθεμία μπορεί να εγκατασταθεί διαφορετικό σύστημα αρχείων, με μία διαδικασία γνωστή ως διαμόρφωση (format), ώστε στη συνέχεια κάθε κατάτμηση να είναι ορατή στον χρήστη σαν διαφορετικός δίσκος. Αμέσως μετά από μία διαμόρφωση, το σύστημα αρχείων είναι κενό: δεν περιέχει εγγραφές περί αρχείων και η πλήρης χωρητικότητα της κατάτμησης είναι διαθέσιμη στον χρήστη για αποθήκευση δεδομένων (εκτός από τον αόρατο χώρο που δεσμεύεται για τις δομές του ίδιου του συστήματος αρχείων).
    oΚάθε ΛΣ υποστηρίζει διαφορετικούς τύπους συστημάτων αρχείων, οι οποίοι διαφέρουν μεταξύ τους ως προς τις εσωτερικές τους συμβάσεις και τους χρησιμοποιούμενους αλγορίθμους (π.χ. μέγεθος των μπλοκ, δομές δεδομένων που αξιοποιούν, αποθηκευόμενα μεταδεδομένα κλπ), αλλά και ως προς τις δυνατότητες χειρισμού αρχείων που παρέχουν στους χρήστες. Έτσι στα Windows επικρατούν τα συστήματα αρχείων «FAT32» και «NTFS», ενώ στο Linux τα «ext3», «ext4» και «ReiserFS».

    Δομημένος Προγραμματισμός Η/Υ σε C: Διαλέξεις 2 - 12 – Σύνταξη, Τελεστές και Τύποι Δεδομένων, Κωδικοποίηση Αλγορίθμων και Δομών Δεδομένων, Πρότυπη Βιβλιοθήκη της C

    ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ ΣΕ C
    ΘΕΩΡΙΑ

    2 - 12: Σύνταξη, Τελεστές και Τύποι Δεδομένων,
    Κωδικοποίηση Αλγορίθμων και Δομών Δεδομένων,
    Πρότυπη Βιβλιοθήκη της C
    ΠΕΡΙΕΧΟΜΕΝΑ


    • ΣΗΜΕΙΩΣΕΙΣ
      • Διαλέξεις δομημένου προγραμματισμού Η/Υ σε C υπάρχουν εδώ (Πάνος Βασιλειάδης, από http://www.cs.uoi.gr/~cs423/)! Στην οθόνη η οποία θα εμφανιστεί, επιλέξτε «File» («Αρχείο» στα ελληνικά) και στη συνέχεια «Download» («Λήψη» στα ελληνικά).


    • ΕΠΙΣΗΜΑΝΣΕΙΣ
      • Διαφορές από τη μεταγενέστερη C++:
        • Στη C δεν υπάρχουν οι τύποι δεδομένων bool και String, ούτε οι δεσμευμένες λέξεις κλειδιά 'true' και 'false'. Η λογική αλήθεια συμβολίζεται με οποιονδήποτε θετικό ακέραιο αριθμό, ενώ το λογικό ψεύδος με την αριθμητική τιμή 0.
        • Στη C δεν υπάρχουν οι τελεστές new και delete (new[] και delete[] για πίνακες). Αντ' αυτών είναι διαθέσιμες μόνον οι συναρτήσεις malloc() και free().
        • Η C δεν υποστηρίζει πρότυπα (templates).
        • Η C δεν υποστηρίζει υπερφόρτωση τελεστών.
        • Η C δεν υποστηρίζει τη βιβλιοθήκη έτοιμων δομών δεδομένων STL.
        • Στη C η είσοδος / έξοδος δεδομένων γίνεται αποκλειστικά μέσω των συναρτήσεων της βιβλιοθήκης stdio.h [printf(), scanf(), fprintf(), fscanf(), puts(), fputs(), putc(), fputc(), getchar() κλπ], ενώ στη C++ συνήθως μέσω της βιβλιοθήκης iostream (cout, cin κλπ).
        • Στη C είναι απαραίτητη η προσθήκη της δεσμευμένης λέξης-κλειδί 'struct' αμέσως πριν από κάθε δήλωση στιγμιοτύπου μίας δομής.
        • Η C έχει μικρότερη σε μέγεθος και υπολογιστικές απαιτήσεις πρότυπη βιβλιοθήκη. Τα μεγάλα προγράμματα σε C συνήθως είναι ελαφρώς ταχύτερα και μεταγλωττίζονται ελαφρώς γρηγορότερα από αντίστοιχης κλίμακας προγράμματα σε C++.
        • Η C είναι αποκλειστικά γλώσσα διαδικαστικού και δομημένου προγραμματισμού, χωρίς φυσικά καμία υποστήριξη αντικειμενοστρέφειας (κλάσεις, αντικείμενα, κληρονομικότητα, πολυμορφισμός,  υποσκέλιση συναρτήσεων, υπερφόρτωση συναρτήσεων, διασυνδέσεις κλπ).
      • Στη C ένα αλφαριθμητικό μπορεί να αποθηκευτεί μόνο σε μονοδιάστατο πίνακα τύπου char (πίνακας χαρακτήρων) και τερματίζεται με τον ειδικό χαρακτήρα '\0' (ΟΧΙ '\n'), ο οποίος καταλαμβάνει μία θέση στον πίνακα.
      • Στη C το όνομα ενός πίνακα είναι δείκτης προς το πρώτο στοιχείο του ο οποίος δεν  δύναται να αλλάξει τιμή. Eπομένως  ο τύπος δεδομένων char[] ισοδυναμεί με τον const char*.
      • Στη C ο χειρισμός των αλφαριθμητικών (αντιγραφή, συνένωση, σύγκριση κλπ) γίνεται με τις συναρτήσεις της βιβλιοθήκης string.h [strcmp(), strcpy(), strcat(), strncat(), strncmp() κλπ], και ΟΧΙ με συνηθισμένους τελεστές οι οποίοι επενεργούν σε μεταβλητές βασικών τύπων δεδομένων (+, =, != κλπ).
      • Κάθε τύπος δεδομένων μπορεί να καταλαμβάνει διαφορετικό πλήθος byte, αναλόγως με την αρχιτεκτονική του υπολογιστή όπου εκτελείται το πρόγραμμα. Από το πόσα byte καταλαμβάνει κάθε μεταβλητή του εν λόγω τύπου όταν αποθηκεύεται στη μνήμη, εξαρτάται το εύρος τιμών που μπορούν να λάβουν οι μεταβλητές αυτού του τύπου κατά τον χρόνο εκτέλεσης.
      • Σε συνηθισμένα PC με επεξεργαστές των 32-bit, ισχύουν τα εξής:


              Τύπος     Byte  Bit                Εύρος τιμών


             short int    2   16          -32,768 -> +32,767          
    unsigned short int    2   16                0 -> +65,535     
          unsigned int    4   16                0 -> +4,294,967,295
                   int    4   32   -2,147,483,648 -> +2,147,483,647
              long int    4   32   -2,147,483,648 -> +2,147,483,647
           signed char    1    8             -128 -> +127
         unsigned char    1    8                0 -> +255
                 float    4   32
                double    8   64
           long double   12   96  
      • Προτεραιότητα τελεστών.
      • Κανόνες αυτόματης ανάθεσης τύπου.

    <Β>ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ C ΔΟΜΗΜΕΝΟΣ STRUCTURED PROGRAMMING PROCEDURAL C++ ΔΙΑΔΙΚΑΣΙΕΣ ΣΥΝΑΡΤΗΣΕΙΣ PROCEDURES FUNCTIONS


    Τρίτη 8 Φεβρουαρίου 2011

    Δομημένος Προγραμματισμός Η/Υ σε C: Διάλεξη 1 - Λογισμικό Συστήματος και Δομημένος Προγραμματισμός

    ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ ΣΕ C
    ΘΕΩΡΙΑ

    1: Λογισμικό Συστήματος και Δομημένος Προγραμματισμός
    ΣΥΝΙΣΤΩΜΕΝΑ ΠΡΟΑΠΑΙΤΟΥΜΕΝΑ
    ΕΙΣΑΓΩΓΗ ΣΤΗ ΦΥΣΙΚΗ (υπό κατασκευή)
    ΕΙΣΑΓΩΓΗ ΣΤΗ ΘΕΩΡΗΤΙΚΗ ΠΛΗΡΟΦΟΡΙΚΗ (υπό κατασκευή)



    ΠΕΡΙΕΧΟΜΕΝΑ


    ΕΙΣΑΓΩΓΗ ΣΤΟΥΣ ΥΠΟΛΟΓΙΣΤΕΣ
        Στην επικρατούσα εκδοχή του, ο υπολογιστής είναι ένα σχεδιασμένο με κατάλληλο τρόπο σύνολο από αλληλεξαρτώμενα μηχανικά και – κυρίως – ηλεκτρονικά εξαρτήματα και κυκλώματα, με κυριότερα θεμελιώδη συστατικά του τα τρανζίστορ. Αυτά είναι μικροσκοπικοί ηλεκτρικοί διακόπτες ημιαγώγιμου υλικού, καθένας από τους οποίους μπορεί να κωδικοποιεί με ελεγχόμενο τρόπο δύο αμοιβαίως αποκλειόμενες αριθμητικές τιμές: «0» (όταν δεν άγει ηλεκτρικό ρεύμα – μονωτής) και «1» (όταν άγει ηλεκτρικό ρεύμα – αγωγός). Η μεγάλη σπουδαιότητά τους, η οποία τα έχει καταστήσει σημαντικότερη ίσως τεχνολογική εφεύρεση του 20ου αιώνα, απορρέει από τη δυνατότητα εύκολης κατασκευής διατάξεων εώς και δισεκατομμυρίων τρανζίστορ σε πολύ μικρές επιφάνειες ημιαγώγιμου μεταλλοειδούς υλικού. Τα εξαρτήματα ενός υπολογιστή, συμπεριλαμβανομένων τέτοιων διατάξεων από τρανζίστορ (μικροτσίπ ή ολοκληρωμένα κυκλώματα), είναι σχεδιασμένα καταλλήλως ώστε, συνολικά, να «υλοποιούν» μία Καθολική Μηχανή Turing με αλφάβητο το δυαδικό αριθμητικό σύστημα! Ως αποτέλεσμα, ένας ηλεκτρονικός υπολογιστής (Η / Υ) είναι θεωρητικά σε θέση να εκτελέσει κάθε δυνατό υπολογισμό, υπό ορισμένες προϋποθέσεις.
        Έτσι, τα εξαρτήματα ενός υπολογιστή συνεργάζονται προκειμένου να εκτελούν προγράμματα: αλληλουχίες εντολών οι οποίες υλοποιούν αλγορίθμους και κωδικοποιούνται ως διατεταγμένα σύνολα αριθμών στο δυαδικό σύστημα, προκειμένου να είναι καταληπτές από τον υπολογιστή. Ως γνωστόν, κάθε αλγόριθμος ισοδυναμεί μαθηματικώς με μία συγκεκριμένη Μηχανή Turing και επομένως μπορεί να εκτελεστεί από μία Καθολική Μηχανή Turing. Κάθε πρόγραμμα λειτουργεί επεξεργαζόμενο δεδομένα εισόδου και παράγοντας δεδομένα εξόδου, επίσης κωδικοποιούμενα αριθμητικά στο δυαδικό σύστημα. Προαιρετικά, τα εν λόγω δεδομένα εξόδου εύκολα απεικονίζονται στον φυσικό κόσμο σε κάποια μορφή, μέσω κατάλληλων περιφερειακών συσκευών εξόδου συνδεδεμένων με τον υπολογιστή (π.χ. οθόνη, εκτυπωτής, ηχεία κλπ). Οι εντολές οι οποίες συναποτελούν τα προγράμματα επιλέγονται από ένα σύνολο δυνατών εντολών που ο επεξεργαστής (CPU, ή Κεντρική Μονάδα Επεξεργασίας), το κεντρικό μικροτσίπ του υπολογιστή, είναι σχεδιασμένος ώστε να «αντιλαμβάνεται». Στην πραγματικότητα τα ηλεκτρονικά κυκλώματα στο εσωτερικό του επεξεργαστή είναι απλώς «καλωδιωμένα» κατάλληλα ώστε, όταν τροφοδοτούνται ηλεκτρικά με μία ακολουθία δυαδικών αριθμητικών ψηφίων (bit, με δυνατές τιμές «0» και «1») η οποία αποτελεί τον κώδικα αναγνώρισης μίας γνωστής εντολής, να συμπεριφέρονται με έναν προσχεδιασμένο τρόπο που αποδίδει το ζητούμενο αποτέλεσμα.
        Το σύνολο των εν λόγω δυνατών αποτελεσμάτων ορίζει και το σύνολο των δυνατών, αναγνωρίσιμων από τη CPU εντολών. Ευτυχώς, αν στόχος είναι μόνον ο υπολογιστής να ισοδυναμεί θεωρητικά με μία Καθολική Μηχανή Turing ώστε να είναι σε θέση να εκτελεί κάθε έγκυρο αλγόριθμο, τότε είναι γνωστές και περιορισμένες σε πλήθος οι απαιτούμενες εντολές τις οποίες ο επεξεργαστής πρέπει να είναι σχεδιασμένος ώστε να αναγνωρίζει. Φυσικά, οι περισσότερες απ' αυτές είναι αναγκαίο να συνοδεύονται από δεδομένα, «ορίσματα» αριθμητικά κωδικοποιημένα στο δυαδικό σύστημα, τα οποία επηρεάζουν ή από τα οποία επηρεάζονται: δύο εκτελέσεις της ίδιας εντολής με διαφορετικά ορίσματα επιφέρουν διαφορετικό αποτέλεσμα. Οι αντιληπτές από τον επεξεργαστή εντολές συνήθως αφορούν τη διενέργεια στοιχειωδών αριθμητικών και λογικών πράξεων σε δεδομένα π. χ. πρόσθεση ή λογική άρνηση , το «άλμα» σε ένα σημείο του προγράμματος ώστε να καθοριστεί ρητά η επόμενη προς εκτέλεση εντολή, ή την «εγγραφή» / «ανάγνωση» στην κύρια μνήμη RAM, όπου αποθηκεύονται οι εντολές και τα δεδομένα ενός προγράμματος όταν αυτό εκτελείται από τον επεξεργαστή. Άρα, οι εντολές οι οποίες συνιστούν ένα πρόγραμμα είναι τοποθετημένες συνεχόμενα στη RAM και ο επεξεργαστής τις λαμβάνει από εκεί διαδοχικά, με μόνη εξαίρεση την περίπτωση όπου η εκτέλεση μίας εντολής άλματος αλλάζει το σημείο της μνήμης από όπου «διαβάζονται» οι τροφοδοτούμενες στη CPU εντολές.
        Τα προγράμματα συγγράφονται από προγραμματιστές ως κατάλληλες αλληλουχίες τέτοιων εντολών που, συνολικά, επιτυγχάνουν έναν σκοπό: συνήθως τον μετασχηματισμό δεδομένων εισόδου σε δεδομένα εξόδου, ύστερα από τον υπολογισμό που επιτελεί ένας αλγόριθμος. Το σύνολο των προγραμμάτων ενός υπολογιστή καλείται λογισμικό (software), κατ’ αντιδιαστολή προς το σύνολο των μηχανικών και ηλεκτρονικών εξαρτημάτων του το οποίο λέγεται υλικό (hardware). Εξίσου σημαντικό εξάρτημα με τη CPU είναι και η μνήμη RAM, με τις δυο τους να διασυνδέονται μέσω ενός ηλεκτρικού αγωγού, του διαύλου, διά του οποίου διαρκώς μεταφέρονται από τη μνήμη προς τον επεξεργαστή η επόμενη προς εκτέλεση εντολή και δεδομένα εισόδου (ανάγνωση από τη RAM), ή δεδομένα εξόδου από τη CPU προς τη μνήμη (εγγραφή στη RAM). Η τελευταία είναι τυχαίας προσπέλασης και η ομοιότητά της με την ταινία του αφηρημένου θεωρητικού υπολογιστικού μοντέλου της Μηχανής Turing Τυχαίας Προσπέλασης είναι προφανής.
        Η RAM είναι σχεδιασμένη ως μία γιγάντια αλληλουχία σειριακά αριθμημένων «ηλεκτρονικών κελιών», σε θέση να αποθηκεύουν μία οκτάδα δυαδικών ψηφίων το καθένα. Αυτά τα κελιά ονομάζονται byte και το καθένα μπορεί να διαβαστεί ή να εγγραφεί από τον επεξεργαστή ξεχωριστά, με βάση την αρίθμησή του (διεύθυνση μνήμης). Ένα byte ανά πάσα στιγμή κωδικοποιεί δυαδικά έναν από 256 διαφορετικούς αριθμούς, αφού οι δυνατοί διακριτοί συνδυασμοί τιμών μίας οκτάδας bit είναι 28 = 256. Το σύνολο των δυνατών διευθύνσεων μνήμης ενός υπολογιστή ονομάζεται χώρος διευθύνσεων, ενώ οι διευθύνσεις απαιτείται να μπορούν να αποθηκεύονται ως δεδομένα προγραμμάτων στη RAM (π.χ. ορίσματα σε εντολές ανάγνωσης ή εγγραφής στη μνήμη), επομένως αναγκαστικά κωδικοποιούνται στο δυαδικό σύστημα εφόσον η RAM είναι απλώς μία γιγάντια, διατεταγμένη και διαμερισμένη σε byte συλλογή από bit. Όπως είναι μάλλον αναμενόμενο, συνήθως κάθε bit υλοποιείται φυσικά με χρήση ενός τρανζίστορ.
        Τα περιεχόμενα της μνήμης RAM διαγράφονται κάθε φορά που διακόπτεται η παροχή ηλεκτρικού ρεύματος προς αυτήν. Γι’ αυτόν τον λόγο τα προγράμματα και τα μόνιμα δεδομένα των υπολογιστών συνήθως είναι αποθηκευμένα σε συσκευές δευτερεύουσας αποθήκευσης: μαγνητικές (π.χ. σκληροί δίσκοι, δισκέτες), οπτικές (π.χ. CD-ROM, DVD-ROM, Blu-Ray) ή μνήμες FLASH (π.χ. φλασάκια USB, δίσκοι στερεάς κατάστασης). Οι εν λόγω συσκευές δεν απαιτούν διαρκή παροχή ηλεκτρισμού και χαρακτηρίζονται από πολύ μεγαλύτερη χωρητικότητα, με πολύ μικρότερο κόστος, αλλά και μειωμένη ταχύτητα προσπέλασης δηλαδή ανάγνωσης και εγγραφής –, σε σχέση με την κύρια μνήμη RAM. Ενδεικτικά, σήμερα κυκλοφορούν σκληροί δίσκοι των περίπου 2000 Gigabyte (2000 GB = 2 * 1000 * 1024 * 1024 * 1024 byte) σε υπολογιστές με κύρια μνήμη των 8 GB. Προκειμένου να εκτελεστεί ένα πρόγραμμα, οι εντολές που το συναποτελούν και τα δεδομένα εισόδου μεταφέρονται αναγκαστικά από μία συσκευή δευτερεύουσας αποθήκευσης στη μνήμη RAM, απ' όπου στη συνέχεια τροφοδοτούνται διαδοχικά στον επεξεργαστή.
        Το μέγεθος του χώρου διευθύνσεων, το πόσα διακριτά byte είναι σε θέση να διευθυνσιοδοτήσει ένας υπολογιστής, είναι αναγκαστικά αριθμητική δύναμη του 2, εφόσον μία διεύθυνση δυαδικά κωδικοποιημένη και αποθηκευόμενη σε n bit δύναται να λάβει το πολύ 2n διαφορετικές τιμές. Ως αποτέλεσμα, για λόγους ευκολίας, τα μικροτσίπ της RAM κατασκευάζονται με χωρητικότητες (μετρούμενες σε πλήθος byte) πολλαπλάσιες δυνάμεων του 2. Έτσι, από τη δεκαετία του 1960 κι έπειτα, επικράτησε τα μεγέθη κύριας μνήμης των υπολογιστών – με το byte ως βασική μονάδα – να μετρώνται ως πολλαπλάσια δυνάμεων του 2 και όχι του 10, όπως συνηθίζεται στις επιστήμες: π.χ. 1 kilobyte (KB) = 10241 = 210 byte, ενώ ενδεικτικά 1 kilowatt (KW) = 10001 = 103 watt. Ωστόσο οι κατασκευαστές συσκευών δευτερεύουσας αποθήκευσης συνηθίζουν να εννοούν τα πολλαπλάσια του byte ως δυνάμεις του 10, διότι στα εν λόγω μέσα δεν υφίσταται το ζήτημα της δυαδικής διευθυνσιοδότησης. Για να αποφεύγεται η σύγχυση, το 1998 τυποποιήθηκαν νέοι συμβολισμοί και νέα ονόματα για τις δυαδικές μονάδες, αποκλειστικά και μόνο για τα πολλαπλάσια του byte:
        
    Δεκαδικό Σύστημα Δυαδικό Σύστημα
    Τιμή Μονάδα Τιμή Μονάδα
    1000  k kilo- (κίλο-)
    1024ki kibi- (κίμπι-)
    10002  M  mega- (μέγα-)
    10242  Mi  mebi- (μέμπι-)
    10003  G giga- (γίγα-)10243  Gi gibi- (γίμπι-)
    10004  T tera- (τέρα-)10244  Ti tebi- (τέμπι-)
    10005  P peta- (πέτα-)10245  Pi pebi- (πέμπι-)
    10006  E exa- (έξα-)10246  Ei exbi- (έξμπι-)
    10007 Z zetta- (ζέτα-)10247 Zi zebi- (ζέμπι-)
    10008 Y yotta- (γιότα-)10248 Yi yobi- (γιόμπι-)

        Τα σταθερά, αποθηκευμένα σε δευτερεύουσα μνήμη δεδομένα (π.χ. στον σκληρό δίσκο, σε φλασάκι USB κ.α.) είναι ομαδοποιημένα σε αρχεία. Ένα αρχείο είναι μία αλληλουχία από byte, διαθέσιμη για ανάγνωση από προγράμματα που το ζητούν, και ο τύπος του καθορίζει κανόνες για το πώς πρέπει να είναι οργανωμένα τα δεδομένα του και πώς πρέπει να ερμηνεύονται από ένα πρόγραμμα. Τα δεδομένα ορισμένων τύπων αρχείων (αρχεία κειμένου) είναι αλφαριθμητικοί χαρακτήρες αριθμητικά κωδικοποιημένοι σύμφωνα με κάποια σύμβαση: π.χ. ο κώδικας ASCII, με τον οποίον αλφαβητικοί χαρακτήρες, αριθμητικά ψηφία και ειδικοί χαρακτήρες (όπως η «αλλαγή γραμμής» ή η «εσοχή παραγράφου») αντιστοιχίζονται μονοσήμαντα σε κάποιον σταθερό αριθμό, είναι μία τέτοια κοινώς αποδεκτή σύμβαση. Κάθε πρόγραμμα σχεδιασμένο έτσι ώστε να αναγνωρίζει τον κώδικα ASCII, είναι σε θέση να ανοίξει και να αναγνώσει αρχεία κειμένου. Υπάρχουν ωστόσο και τύποι αρχείων πολυμέσων (π.χ. εικόνα, βίντεο ή ήχος), ειδικοί τύποι αρχείων αναγνώσιμων μόνο από το πρόγραμμα που τα δημιούργησε, αλλά και δυαδικά αρχεία, τα οποία εκφράζονται απλώς ως μία ακατέργαστη, συνεχόμενη ροή από byte.
        Επειδή ένα πρόγραμμα σε γλώσσα μηχανήςγλώσσα πρώτης γενιάς) – σε μορφή άμεσα εκτελέσιμη από τον επεξεργαστή – δεν είναι παρά μία μεγάλη και εξαιρετικά δυσανάγνωστη αλληλουχία δυαδικών ψηφίων, τα προγράμματα συγγράφονται ως διατεταγμένα σύνολα κατάλληλων συμβολοσειρών σε γλώσσες προγραμματισμού υψηλού επιπέδου ή τρίτης γενιάς: τυπικές γλώσσες με αυστηρή και τυποποιημένη σύνταξη, αλλά βασισμένες θεμελιωδώς σε μια περιορισμένη διάλεκτο της αγγλικής και με αλφάβητο ένα μεγάλο υποσύνολο των χαρακτήρων του κώδικα ASCII. Ένα πρόγραμμα αναπτυγμένο σε γλώσσα τρίτης γενιάς στηρίζεται λεξιλογικά σε λέξεις-κλειδιά, συμβολικά ονόματα μεταβλητών και παρόμοιες αφαιρέσεις υψηλού επιπέδου, είναι εγγύτερο στον ψευδοκώδικα – φυσικότερο για τον Άνθρωπο μηχανισμό διατύπωσης αλγορίθμων εν συγκρίσει με τη γλώσσα μηχανής – και μοιάζει άμεσα κατανοητό από αναλόγως καταρτισμένα άτομα. Συγγράφεται από τους προγραμματιστές σε συνήθη αρχεία κειμένου τα οποία πρέπει στη συνέχεια να υποστούν μεταγλώττιση σε δυαδικά αρχεία γλώσσας μηχανής, προκειμένου να καταστούν ικανά να «φορτωθούν» (δηλαδή να μεταφερθούν) στην κύρια μνήμη ως προγράμματα και να «τρέξουν» (δηλαδή να εκτελεστούν) στον επεξεργαστή.
        Λογισμικό χρήστη (user software), ή εφαρμογές, ονομάζεται το σύνολο των προγραμμάτων υπολογιστή τα οποία χειρίζονται άμεσα οι χρήστες προκειμένου να εκτελέσουν τις εργασίες τους (π.χ. εφαρμογές γραφείου, εφαρμογές πολυμέσων, βιντεοπαιχνίδια, επιστημονικοί προσομοιωτές, βοηθητικά εργαλεία κλπ). Λογισμικό συστήματος (system software), κατ’ αντιδιαστολή, ονομάζεται το σύνολο των προγραμμάτων υπολογιστή τα οποία δεν προορίζονται για τους χρήστες, αλλά υποβοηθούν και επιτρέπουν την κατασκευή και τη λειτουργία των εφαρμογών (π.χ. μεταγλωττιστές, βιβλιοθήκες, συμβολομεταφραστές, λειτουργικά συστήματα κλπ). Το λειτουργικό σύστημα (ΛΣ) συνιστά το σπουδαιότερο τμήμα του λογισμικού συστήματος: αποτελεί τον κύριο μεσολαβητή μεταξύ υλικού και λογισμικού και εκτελείται διαρκώς στο υπόβαθρο όσο λειτουργεί ο υπολογιστής. Κύριος ρόλος του είναι να διαχειρίζεται αυτοματοποιημένα τους πόρους του υλικού (π.χ. χρόνος στον επεξεργαστή, χώρος στη μνήμη ή στον δίσκο, πρόσβαση σε περιφερειακές συσκευές όπως ο εκτυπωτής κλπ) και να τους κατανέμει με ελεγχόμενο τρόπο στις εφαρμογές.
        Ένα αρχείο κειμένου με πηγαίο κώδικα, συντεταγμένο σε μία γλώσσα προγραμματισμού υψηλού επιπέδου (π.χ. C, PASCAL, BASIC, C++ κλπ), μεταφράζεται σε ένα αντίστοιχο αρχείο συμβολικού κώδικα (assembly) από τον κατάλληλο μεταγλωττιστή (compiler): πρόγραμμα προσαρμοσμένο στην εκάστοτε γλώσσα υψηλού επιπέδου και εξειδικευμένο στην αναγνώριση αλφαριθμητικών συμβολοσειρών της. Το προκύπτον συμβολικό αρχείο στη συνέχεια μετασχηματίζεται σε αντικειμενικό αρχείο γλώσσας μηχανής από έναν συμβολομεταφραστή (assembler), μία διαδικασία που μετατρέπει τον κώδικα σε δυαδικό αρχείο άμεσα εκτελέσιμο από τον επεξεργαστή. Η συμβολική γλώσσα (ή γλώσσα δεύτερης γενιάς) και η γλώσσα μηχανής είναι όχι απλώς εκφραστικά ισοδύναμες, αλλά ίδιου επιπέδου και με αμφιμονοσήμαντη αντιστοιχία μεταξύ των μεμονωμένων εντολών τους. Η συμβολική όμως στηρίζεται σε ένα αλφάβητο αποτελούμενο από χαρακτήρες του λατινικού αλφαβήτου και δεκαεξαδικά αριθμητικά ψηφία, ώστε να είναι στοιχειωδώς κατανοητή και ευκολότερα απομνημεύσιμη από τον Άνθρωπο. Συνιστά μία φορμαλιστική σημειογραφία διατύπωσης υπολογιστικών διαδικασιών και – καθόλου συμπτωματικά – μπορεί να θεωρηθεί επεκταμένη εκδοχή της βασικής γλώσσας στην οποία συντάσσονται τα προγράμματα των Μηχανών Turing Τυχαίας Προσπέλασης. Αντιθέτως, η γλώσσα μηχανής συντίθεται αποκλειστικά από bit: ένα εκτελέσιμο αρχείο γλώσσας μηχανής, δηλαδή ο κώδικας ενός προγράμματος σε μορφή άμεσα εκτελέσιμη από τον επεξεργαστή, δεν είναι παρά μία μεγάλη αλληλουχία δυαδικών ψηφίων. Μία εντολή γλώσσας προγραμματισμού υψηλού επιπέδου συνήθως μεταφράζεται σε πολλαπλές διαδοχικές εντολές συμβολικής γλώσσας (χαμηλού επιπέδου), ενώ ακόμα ο μεταγλωττιστής μετατρέπει τα ονόματα μεταβλητών του πηγαίου κώδικα σε αριθμητικές διευθύνσεις μνήμης.
        Είναι προφανές ότι οι δυνατές συμβολικές εντολές, ή εναλλακτικά οι ανάλογες και ίσες σε πλήθος αντίστοιχες δυαδικές, ουσιαστικά συνιστούν το σύνολο των στοιχειωδών εντολών που «αντιλαμβάνεται» ο επεξεργαστής, αυτές που καθοδηγούν άμεσα τα κυκλώματά του κατά την εκτέλεση ενός προγράμματος. Υπάρχουν επεξεργαστές με διαφορετικό πλήθος, σύνταξη, σημασιολογία και μορφή τέτοιων εντολών χαμηλού επιπέδου – τότε μιλάμε για επεξεργαστές διαφορετικής «αρχιτεκτονικής». Στα συνηθισμένα επιτραπέζια και φορητά PC επικρατεί εδώ και τρεις δεκαετίες η αρχιτεκτονική επεξεργαστών «x86» σε ορισμένες παραλλαγές (π.χ. IA-32 και x86-64), όπως διαμορφώθηκε με τον καιρό από τις εταιρείες ημιαγωγών Intel και AMD. Κάθε μεταγλωττιστής και κάθε συμβολομεταφραστής πρέπει να συγγράφεται σε πολλαπλές εκδόσεις με διαφορετικό πηγαίο κώδικα, με την καθεμιά να παράγει αντικειμενικά αρχεία κατάλληλα για μία ξεχωριστή αρχιτεκτονική επεξεργαστών την οποία ο μεταγλωττιστής στοχεύει. Επομένως υπάρχουν τόσες συμβολικές γλώσσες όσες και αρχιτεκτονικές, αλλά ιδανικά μόνο μία κοινώς αποδεκτή εκδοχή κάθε γλώσσας υψηλού επιπέδου.
        Πέρα από τη μεταγλώττιση του κώδικα υψηλού επιπέδου, ήδη από τη δεκαετία του 1950 εμφανίστηκε ως εναλλακτική επιλογή η διερμηνεία. Ένας διερμηνέας είναι μία παραλλαγή μεταγλωττιστή η οποία δεν παράγει αντικειμενικά και εκτελέσιμα δυαδικά αρχεία. Αντ' αυτού, διαβάζει μία-μία τις εντολές του πηγαίου κώδικα, μεταφράζοντας σε γλώσσα μηχανής και εκτελώντας την καθεμιά ξεχωριστά, προτού προχωρήσει στην επόμενη. Έτσι η μετάφραση και η εκτέλεση του προγράμματος συμπίπτουν χρονικά και διαπλέκονται, αλλά φυσικά προκειμένου να τρέξει κανείς ένα διερμηνευόμενο πρόγραμμα πρέπει να είναι εγκατεστημένο στον υπολογιστή του όχι μόνο το επίμαχο αρχείο πηγαίου κώδικα, μα και μία κατάλληλη υλοποίηση του διερμηνέα! Αν και είναι εφικτό να είναι ο ίδιος ο διερμηνέας με τη σειρά του ένα διερμηνευόμενο πρόγραμμα, πρέπει τελικά να τρέχει στο υπόβαθρο ένας άμεσα εκτελέσιμος από τον επεξεργαστή διερμηνέας, άρα ένα μεταγλωττισμένο πρόγραμμα, ο οποίος να εκτελεί τον διερμηνευόμενο επομένως οι γλώσσες αυτές δεν είναι κατάλληλες για την ανάπτυξη λογισμικού συστήματος και οι διερμηνείς συνήθως αναπτύσσονται σε μεταγλωττιζόμενες γλώσσες. Η χρονική επίδοση των διερμηνευόμενων προγραμμάτων είναι μειωμένη σε σύγκριση με ισοδύναμα μεταγλωττισμένα, αφού η μετάφραση σε γλώσσα μηχανής δεν λαμβάνει χώρα μόνο μία φορά αλλά εκ νέου σε κάθε εκτέλεση του προγράμματος!
        Το βασικό πλεονέκτημα των διερμηνέων είναι ότι επιταχύνουν την υλοποίηση και την αποσφαλμάτωση λογισμικού στη φάση της ανάπτυξής του, εφ' όσον δεν απαιτείται εκ νέου μεταγλώττιση μετά από κάθε αλλαγή στον πηγαίο κώδικα. Επίσης, παρέχουν ενισχυμένες δυνατότητες ελέγχου επί του παραγόμενου δυαδικού κώδικα γλώσσας μηχανής και άρα της λειτουργίας του εκάστοτε διερμηνευόμενου προγράμματος: ενώ στη μεταγλώττιση ορισμένες παράμετροι της λειτουργίας αυτής πρέπει να τεθούν αναγκαστικά μία φορά, κατά τον λεγόμενο χρόνο μεταγλώττισης, με τη διερμηνεία οι εν λόγω παράμετροι μπορούν να αναπροσαρμόζονται δυναμικά αναλόγως με τις τρέχουσες συνθήκες σε κάθε τρέξιμο του προγράμματος σε κάθε ξεχωριστό υπολογιστή, κατά τον χρόνο εκτέλεσης, αφού η μετάφραση σε γλώσσα μηχανής και η εκτέλεση συμπίπτουν χρονικά! Οι μεταγλωττιστές και οι διερμηνείς από κοινού ονομάζονται μεταφραστές, ενώ παρομοίως με τους χρόνους μεταγλώττισης και εκτέλεσης ορίζεται και ο χρόνος σύνδεσης.
        Βιβλιοθήκη (library) καλείται μια συλλογή από έτοιμα, ήδη μεταγλωττισμένα υποπρογράμματα που χρησιμοποιείται για τη διευκόλυνση της ανάπτυξης λογισμικού. Οι βιβλιοθήκες περιέχουν δυαδικό κώδικα και δομές δεδομένων, παρέχοντας έτσι «υπηρεσίες» σε προγράμματα και επιτρέποντας τον εύκολο διαμοιρασμό και τη συστηματική επαναχρησιμοποίηση τμημάτων λογισμικού με αρθρωτό (modular) τρόπο, μεταξύ διαφορετικών προγραμμάτων. Τα σύγχρονα λειτουργικά συστήματα παρέχουν βιβλιοθήκες που υλοποιούν την πλειονότητα των υπηρεσιών χαμηλού επιπέδου του συστήματος (π.χ. λογισμικό ανταλλαγής δεδομένων του επεξεργαστή με περιφερειακές συσκευές). Είναι διαθέσιμες επίσης βιβλιοθήκες υψηλότερου επιπέδου, με υλοποιημένους έτοιμους αλγορίθμους. Έτσι, ο περισσότερος κώδικας που απαιτούν οι σύγχρονες εφαρμογές προσφέρεται από αυτές τις βιβλιοθήκες και δεν χρειάζεται να γραφεί από την αρχή για κάθε νέο πρόγραμμα.
        Οι προγραμματιστές εφαρμογών μπορούν να προσπελάσουν – όταν χρειάζεται – μία υπηρεσία που παρέχεται από κάποια βιβλιοθήκη, «καλώντας» απλώς στον κώδικα υψηλού επιπέδου που συγγράφουν την ανάλογη διαδικασία (procedure) με το κατάλληλο κάθε φορά όρισμα. Η διαδικασία, γνωστή επίσης και ως ρουτίνα, υπορουτίνα, μέθοδος ή συνάρτηση (δεν ταυτίζεται με τη μαθηματική έννοια της συνάρτησης, μα όπως αυτή δέχεται ορίσματα «εισόδου» και προαιρετικά επιστρέφει μία τιμή «εξόδου»), είναι απλώς ένα αυτοτελές σύνολο διαδοχικών εντολών προς εκτέλεση από τον υπολογιστή με καθορισμένο τελικό σκοπό: ένα υποπρόγραμμα. Διαδικασίες δεν περιλαμβάνονται μόνο σε έτοιμες βιβλιοθήκες, αφού στον κώδικα κάθε υπό ανάπτυξη εφαρμογής ο προγραμματιστής είναι ελεύθερος να συγγράψει τις δικές του. Όταν καλείται μία διαδικασία στον χρόνο εκτέλεσης, ο έλεγχος του επεξεργαστή μεταβιβάζεται σ' αυτήν και επιστρέφεται στο κύριο πρόγραμμα όταν αυτή τερματίσει, μέσω εντολών άλματος παραχθέντων από τον μεταγλωττιστή. Συνήθως, κατά την εκτέλεση μίας διαδικασίας τροποποιούνται δεδομένα με τρόπο χρήσιμο για το εξωτερικό πρόγραμμα, χωρίς το τελευταίο να τα χειρίζεται απευθείας. Κάθε διαδικασία μπορεί να κληθεί ανά πάσα στιγμή και πολλαπλές φορές, τόσο από τον κώδικα του εξωτερικού / κύριου προγράμματος το οποίο την περιέχει ή αξιοποιεί τη βιβλιοθήκη η οποία την περιέχει, όσο και από τον κώδικα άλλων διαδικασιών του, ακόμα και να καλέσει τον εαυτό της! Αν και είναι σύνηθες μία διαδικασία να τρέχει επανειλημμένα κατά τον χρόνο εκτέλεσης, τόσο στο πηγαίο αρχείο υψηλού επιπέδου όσο και στο αντικειμενικό αρχείο ο κώδικάς της περιέχεται μόνο μία φορά – οι πολλαπλές κλήσεις της μεταγλωττίζονται απλώς σε κατάλληλες στοιχειώδεις εντολές άλματος.
        Για να αξιοποιήσουν οι προγραμματιστές διαδικασίες παρεχόμενες από εξωτερικές βιβλιοθήκες, πρέπει μόνο να γνωρίζουν το πώς συντάσσονται σε πηγαίο επίπεδο οι κλήσεις προς τις επίμαχες διαδικασίες και όχι το πώς οι τελευταίες έχουν υλοποιηθεί στον έτοιμο, ήδη μεταγλωττισμένο κώδικα της βιβλιοθήκης. Το εν λόγω σύνολο κανόνων σύνταξης κλήσεων προς διαδικασίες βιβλιοθήκης από προγράμματα τα οποία ζητούν τις υπηρεσίες τους, καλείται Διασύνδεση Προγραμματισμού Εφαρμογών της εκάστοτε βιβλιοθήκης («Application Programming Interface», σντμ. «API» ή απλώς διασύνδεση). Ο προγραμματιστής που αναπτύσσει μία εφαρμογή η οποία αξιοποιεί μία εξωτερική βιβλιοθήκη, πρέπει κατά τη συγγραφή του πηγαίου κώδικα να γνωρίζει τη διασύνδεσή της προκειμένου ο κώδικάς του να διενεργεί ορθά τις κατάλληλες κλήσεις. Το API, ένα «συμβόλαιο κλήσης» μεταξύ καλούντος και καλούμενου κώδικα, διαχωρίζει επομένως την προγραμματιστική υλοποίηση κάποιων υπηρεσιών από τη χρήση τους και επιτρέπει την υποβολή και εξυπηρέτηση αιτήσεων ή την ανταλλαγή δεδομένων μεταξύ διαφορετικών τμημάτων λογισμικού.
        Κατά τη μεταγλώττιση ενός προγράμματος, σε κάθε αρχείο κειμένου με πηγαίο κώδικα – είτε αυτό είναι αυτοτελές (κώδικας προγράμματος) είτε όχι (αρχείο με κώδικα βιβλιοθήκης) – αντιστοιχίζεται ένα παραγόμενο αντικειμενικό αρχείο με κώδικα σε δυαδική γλώσσα μηχανής. Κάθε αντικειμενικό αρχείο περιέχει εκτελέσιμο κώδικα, δηλώσεις δεδομένων, έναν πίνακα συμβόλων, όπου ορίζονται τα αναγνωριστικά (ονόματα μεταβλητών, σταθερών ή διαδικασιών) που «εξάγονται» από το αρχείο – δηλώνονται δηλαδή σε αυτό – ή «εισάγονται» στο αρχείο – χρησιμοποιούνται δηλαδή χωρίς να δηλώνονται –, και λοιπές πληροφορίες για τον συνδέτη (linker). Αυτός συνήθως καλείται αυτομάτως αμέσως μετά τον συμβολομεταφραστή, δέχεται ως είσοδο ένα ή περισσότερα αντικειμενικά αρχεία, τα συνενώνει κατάλληλα και παράγει ένα μοναδικό, τελικό εκτελέσιμο αρχείο. Στις περισσότερες περιπτώσεις ο μεταγλωττιστής, ο συμβολομεταφραστής και ο συνδέτης περιέχονται στο ίδιο πακέτο λογισμικού συστήματος. Όταν ο προγραμματιστής δώσει εντολή για μεταγλώττιση ενός ή περισσότερων αρχείων πηγαίου κώδικα, η μετάφραση και η σύνδεση συνήθως ενεργοποιούνται αυτομάτως μετά την ολοκλήρωση της μεταγλώττισης.
        Η συνένωση που επιτελεί ο συνδέτης δεν αφορά μόνο πολλαπλά αντικειμενικά αρχεία (που προκύπτουν προφανώς από αντίστοιχα πολλαπλά πηγαία αρχεία) της ίδιας εφαρμογής, αλλά επεκτείνεται και στο να «επιλύει αναφορές εισαγόμενων συμβόλων»: σαρώνει δηλαδή τον πίνακα συμβόλων κάθε αντικειμενικού αρχείου εισόδου, ανακαλύπτει ποια αναγνωριστικά παρέχονται από εξωτερικές βιβλιοθήκες, αναζητά τον αντικειμενικό κώδικα των εν λόγω βιβλιοθηκών και εισάγει τα κατάλληλα τμήματά του στο τελικό εκτελέσιμο αρχείο της εφαρμογής. Προκειμένου να επιτύχει τους στόχους του ο συνδέτης, ανάμεσα στ' άλλα, προβαίνει σε ένα πρώτο βήμα επανατοποθέτησης. Αυτό σημαίνει ότι κάθε τμήμα κώδικα μηχανής που εισάγει και τακτοποιεί στο τελικό εκτελέσιμο αρχείο, είτε προέρχεται από αντικειμενικό αρχείο που έδωσε ως είσοδο στον συνδέτη ο προγραμματιστής είτε από αντικειμενικό αρχείο εξωτερικής βιβλιοθήκης, το τροποποιεί καταλλήλως ώστε τελικά όλες οι διευθύνσεις μνήμης εντολών και δεδομένων στο τελικό εκτελέσιμο να είναι συνεπείς μεταξύ τους, να μην επικαλύπτονται και να είναι σχετικές ως προς μία κοινή διεύθυνση αναφοράς ως βάση. Το εν λόγω βήμα απαιτείται διότι οι μεταγλωττιστές θεωρούν ξεχωριστό χώρο διευθύνσεων για κάθε αντικειμενικό αρχείο και μεταγλωττίζουν το καθένα με τη δική του διεύθυνση βάσης. Τα αντικειμενικά αρχεία συμμορφώνονται με τις απαιτήσεις προτύπων τα οποία συνήθως εξαρτώνται από το ΛΣ και καθορίζουν τη δομή τους σύμφωνα με κοινώς αποδεκτές συμβάσεις. Τα πρότυπα αυτά αφορούν αντικειμενικά αρχεία παντός είδους, αυτοτελή εκτελέσιμα αρχεία και μεταγλωττισμένες βιβλιοθήκες, έτσι ώστε τελικά κάθε τύπος δυαδικού αρχείου σε υπολογιστές με το ίδιο ΛΣ να έχει μία συγκεκριμένη, προτυποποιημένη δομή.
        Οι βιβλιοθήκες διακρίνονται σε στατικές και σε δυναμικές, ενώ προαιρετικά είναι κοινόχρηστες. Όταν ένα πρόγραμμα καλεί υποπρογράμματα από στατικές βιβλιοθήκες, ο συνδέτης (ο οποίος συμβουλεύεται κατάλληλα αρχεία ρυθμίσεων ή το ΛΣ για να εντοπίσει τα αντικειμενικά αρχεία βιβλιοθηκών στον δίσκο) ενσωματώνει πραγματικά τον δυαδικό τους κώδικα στο παραγόμενο εκτελέσιμο και επανατοποθετεί καταλλήλως τις διευθύνσεις μνήμης σε χρόνο σύνδεσης. Αντιθέτως, οι δυναμικές βιβλιοθήκες ενσωματώνονται και επανατοποθετούνται στον τελικό κώδικα απευθείας στη μνήμη και ενώ το πρόγραμμα εκτελείται, με αποτέλεσμα τα εκτελέσιμα αρχεία να έχουν πολύ μικρότερο μέγεθος αφού περιέχουν απλώς οδηγίες προς έναν συνδέτη χρόνου εκτέλεσης, παρεχόμενου από το ΛΣ, αντί για τον ίδιο τον αντικειμενικό κώδικα των καλούμενων υποπρογραμμάτων βιβλιοθήκης. Απαιτείται ωστόσο η μόνιμη παρουσία του αντικειμενικού αρχείου της βιβλιοθήκης στον δίσκο του εκάστοτε υπολογιστή προκειμένου να είναι δυνατή η εκτέλεση του προγράμματος. Βασικό πλεονέκτημα της προσέγγισης αυτής είναι ότι το εν λόγω αρχείο μπορεί να ενημερωθεί ανά πάσα στιγμή και να αντικατασταθεί από νεότερη έκδοσή του, αξιοποιήσιμη αυτομάτως από τα προγράμματα τα οποία χρησιμοποιούν την επίμαχη βιβλιοθήκη χωρίς να απαιτείται επαναμεταγλώττισή τους!
        Οι δυναμικές βιβλιοθήκες προαιρετικά κατασκευάζονται ως κοινόχρηστες, δηλαδή έτσι ώστε ένας υπολογιστής να διαθέτει μόνο ένα αντίγραφό τους, ικανό να διαμοιράζεται ταυτοχρόνως σε πολλαπλά εκτελούμενα προγράμματα που τις καλούν. Η κοινοχρησία συμβαίνει είτε μόνο στον δίσκο ένα μόνο αντικειμενικό αρχείο της βιβλιοθήκης είτε και στη μνήμη η βιβλιοθήκη φορτώνεται μόνο σε μία περιοχή της μνήμης RAM και όσα προγράμματα την αξιοποιούν την προσπελαύνουν σ' αυτή τη θέση. Επειδή ο τύπος αρχείου των βιβλιοθηκών είναι κοινός με των αυτοτελών εκτελέσιμων και αντικειμενικών αρχείων, ακόμα κι ένα εκτελέσιμο είναι εφικτό να αξιοποιηθεί ως κοινόχρηστη βιβλιοθήκη, υπό την προϋπόθεση πως περιέχει έναν πίνακα συμβόλων για χρήση από τον συνδέτη χρόνου εκτέλεσης, με πληροφορίες για τις διαδικασίες και τις δομές δεδομένων που εξάγει.


    ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΑ ΠΑΡΑΔΕΙΓΜΑΤΑ
        Στην πληροφορική, προγραμματιστικό παράδειγμα καλείται ένα θεμελιώδες ύφος προγραμματισμού υπολογιστών, με βάση το οποίο προσεγγίζονται ένα υπολογιστικό πρόβλημα και η υλοποίηση της αλγοριθμικής λύσης του. Ο όρος επομένως αφορά ένα σύνολο εννοιών που εκφράζουν έναν ορισμένο τρόπο σκέψης και, κατά συνέπεια, την «ενσάρκωση» του αλγορίθμου σε κώδικα υψηλού επιπέδου, διαμορφώνοντας έτσι τον τρόπο σχεδιασμού ενός προγράμματος υπολογιστή. Από το παράδειγμα το οποίο θα επιλέξει ο προγραμματιστής, εξαρτώνται οι αφηρημένες έννοιες με τις οποίες αυτός αντιλαμβάνεται τόσο τις στοιχειώδεις επιμέρους λειτουργίες του προγράμματος, όσο και τα στοιχειώδη επιμέρους «συστατικά» του. Η διάκριση μεταξύ διαφορετικών παραδειγμάτων υφίσταται μόνο στο στάδιο και στο επίπεδο της συγγραφής κώδικα υψηλού επιπέδου, όπου απαιτείται ανθρώπινη προσπάθεια και δημιουργική φαντασία, αφού μετά τη μεταγλώττιση οι στοιχειώδεις λειτουργίες και τα συστατικά του παραχθέντος αντικειμενικού κώδικα έχουν αναχθεί απλώς στη δεδομένη γλώσσα μηχανής της εκάστοτε αρχιτεκτονικής επεξεργαστή.
        Επειδή αρχικά, στις μέρες της δεκαετίας του 1940, ο προγραμματισμός των Η / Υ γινόταν αποκλειστικά σε γλώσσα μηχανής, το πρώτο και απλούστερο προγραμματιστικό παράδειγμα το οποίο εμφανίστηκε ήταν ο προστακτικός προγραμματισμός (imperative programming). Σ' αυτόν, ο πηγαίος κώδικας είναι αντιληπτός ως μία διαδοχή εντολών προς τον υπολογιστή, καθεμιά από τις οποίες αλλάζει την τρέχουσα κατάστασή του. Οι προστακτικές γλώσσες αναγκάζουν τον προγραμματιστή να περιγράψει βήμα προς βήμα τις ζητούμενες από τον επεξεργαστή πράξεις και ενέργειες, με αυστηρή χρονική συνέπεια. Τα θεμελιώδη αφηρημένα συστατικά ενός προστακτικού προγράμματος είναι οι μεταβλητές, οι εντολές και οι δομές δεδομένων, ενώ κεντρική έννοιά του συνιστά ο τελεστής ανάθεσης τιμής σε μεταβλητή. Πρέπει να είναι προφανές πως οι εγγενείς γλώσσες μηχανής των επεξεργαστών είναι αναγκαστικά προστακτικές. Η βασική διαφορά των προστακτικών γλωσσών προγραμματισμού υψηλού επιπέδου από την απλή γλώσσα μηχανής ή συμβολική γλώσσα, είναι ότι κάθε εντολή υψηλού επιπέδου συμπεριλαμβάνει εννοιολογικά συνήθως μία μεγάλη αλληλουχία συμβολικών εντολών, διευκολύνοντας έτσι τον προγραμματιστή, ενώ επίσης υποστηρίζονται με απλό τρόπο σύνθετες αλγοριθμικές δομές επανάληψης και επιλογής, που σε γλώσσα μηχανής πρέπει να υλοποιηθούν αναγκαστικά με πολύπλοκες αλληλουχίες στοιχειωδών εντολών. Ο μεταγλωττιστής και ο συμβολομεταφραστής αναλαμβάνουν φυσικά την αυτοματοποιημένη μετάφραση σε συμβολική γλώσσα / δυαδική γλώσσα μηχανής.
        Η έννοια του προστακτικού προγραμματισμού «βελτιώθηκε» ήδη από τη δεκαετία του 1950 με τον λεγόμενο διαδικαστικό προγραμματισμό (procedural programming). Αυτή είναι μια προχωρημένη εκδοχή προστακτικότητας στηριγμένη στην έννοια της κλήσης διαδικασίας, επιτρέποντας έτσι τη δόμηση του υπό ανάπτυξη προγράμματος ως συλλογή από απομονωμένα μεταξύ τους υποπρογράμματα, μα και την αξιοποίηση εξωτερικών βιβλιοθηκών. Τα δεδομένα εκείνη την εποχή ήταν διαχωρισμένα από τις διαδικασίες και έπρεπε ο προγραμματιστής να καταγράφει χειροκίνητα για κάθε διαδικασία ποιες ρουτίνες αυτή καλούσε, αλλά και ποια δεδομένα τροποποιούσε. Με στόχο τη βελτίωση της αρθρωτής δομής του πηγαίου κώδικα, ώστε να ενισχυθεί η δυνατότητα επαναχρησιμοποίησης τμημάτων του αλλά και η ευκολία ανάγνωσης, κατανόησης και αποσφαλμάτωσής του, κατά τη δεκαετία του 1960 εμφανίστηκε ως εξέλιξη του διαδικαστικού το παράδειγμα του δομημένου προγραμματισμού (structured programming)· ουσιαστικά μία αυστηρότερη και πλουσιότερη περιγραφή της διαδικαστικής προστακτικότητας, υποστηριζόμενη από κατάλληλα χαρακτηριστικά των συμβατών γλωσσών και μεταγλωττιστών.
        Ο δομημένος προγραμματισμός διασπά το βασικό πρόβλημα σε μικρότερα υποπροβλήματα (γνωστά επίσης και ως εργασίες), καθένα από τα οποία ίσως αντιστοιχεί σε έναν συγκεκριμένο και καλώς ορισμένο αλγόριθμο. Κάθε εργασία με πολύπλοκη περιγραφή διαιρείται σε μικρότερες, έως ότου οι εργασίες να είναι αρκετά μικρές, περιεκτικές και απλές στην κατανόηση. Στόχος είναι να καθίσταται ευκολότερη η συγγραφή πολύπλοκων προγραμμάτων, μέσω της υλοποίησης κάθε εργασίας από μία διαδικασία ιδανικά ανεξάρτητη από το εκάστοτε εξωτερικό πρόγραμμα, αλλά παραμετροποιήσιμη χάρη στα ορίσματά της. Ακόμα, το δομημένο παράδειγμα αποθαρρύνει την απότομη μετάβαση της ροής ελέγχου του προγράμματος σε απομακρυσμένα σημεία του κώδικα (με τη, συνηθισμένη παλαιότερα, εντολή άλματος υψηλού επιπέδου goto), ενώ ενθαρρύνει τη σύνταξη του πηγαίου κώδικα έτσι ώστε να είναι οπτικά εμφανή τα μπλοκ εντολών τα οποία περιέχονται σε δομές επανάληψης / επιλογής ή σε διαδικασίες, μέσω σταθερών συμβάσεων παραγραφοποίησης με κατάλληλες εσοχές και εξοχές του κειμένου. Με τον δομημένο προγραμματισμό είναι αποδοτικότερη και ταχύτερη η συντήρηση και η αποσφαλμάτωση του αναπτυσσόμενου λογισμικού, αφού η δόμηση και η οργάνωσή του βασίζονται σε μεγαλύτερες, πολυπλοκότερες και περιεκτικότερες μονάδες – τις διαδικασίες – αντί για μεμονωμένες εντολές.
        Με τον καιρό, οι δομημένες γλώσσες έφτασαν να μην επαρκούν για τη συγγραφή λογισμικού και άρχισαν να ανακύπτουν τα ίδια προβλήματα τα οποία αυτές είχαν πρόσκαιρα επιλύσει, όσο τα προγράμματα γίνονταν όλο και πιο πολύπλοκα. Έτσι ορισμένες προστακτικές γλώσσες επεκτάθηκαν πέρα από το δομημένο παράδειγμα και, ως λύση στα επίμαχα ζητήματα της ευκολίας συντήρησης, αποσφαλμάτωσης και επαναχρησιμοποίησης κώδικα, υιοθετήθηκε κατά τη δεκαετία του 1980 ο λεγόμενος αντικειμενοστρεφής προγραμματισμός (object-oriented programming). Σ' αυτόν, οι δομές δεδομένων, οι μεταβλητές και οι διαδικασίες του πηγαίου κώδικα διαμερίζονται σε ενιαίες, αυτοτελείς, επαναχρησιμοποιήσιμες, συμπαγείς μονάδες εντολών και δεδομένων, τα αντικείμενα. Η λειτουργία του προγράμματος σε υψηλό επίπεδο περιγράφεται μέσω της αλληλεπίδρασης πολλαπλών αντικειμένων, καθώς ένα εξωτερικό τμήμα κώδικα μπορεί να προσπελάσει τα δεδομένα τα οποία περικλείει ένα αντικείμενο μόνο με ελεγχόμενο τρόπο, μέσω των ανάλογων μεθόδων του αντικειμένου (των εγγενών διαδικασιών του).
        Ταυτόχρονα με τις ποικίλες εκδοχές του προστακτικού προγραμματισμού και σε αντιδιαστολή μ' αυτόν, ήδη από τα τέλη της δεκαετίας του 1950 άρχισε να αναπτύσσεται το εναλλακτικό παράδειγμα του δηλωτικού προγραμματισμού (declarative programming). Κύριο χαρακτηριστικό των δηλωτικών γλωσσών υψηλού επιπέδου είναι πως δεν αναγκάζουν τον προγραμματιστή να περιγράψει λεπτομερώς τον αλγόριθμο επίλυσης ενός προβλήματος και τα διαδοχικά επιμέρους βήματα της υλοποίησής του, αλλά απλώς να δηλώσει στον πηγαίο κώδικα μέσω των παρεχόμενων συντακτικών δομών της γλώσσας ποια είναι τα χαρακτηριστικά του ζητούμενου αποτελέσματος δοθέντων των εκάστοτε εισόδων. Στη συνέχεια ο μεταφραστής της γλώσσας (συνήθως διερμηνέας) αναλαμβάνει να εντοπίσει μόνος του σε χρόνο εκτέλεσης τα απαιτούμενα αλγοριθμικά βήματα και να υπολογίσει το αποτέλεσμα εξόδου, με βάση καλώς ορισμένους κανόνες! Τα δηλωτικά προγράμματα, λόγω της διερμηνείας, δεν έχουν πολύ υψηλές επιδόσεις και βεβαίως κατά κανόνα δεν μπορούν να αποτελέσουν λογισμικό συστήματος, ενώ αφαιρούν κάθε ίχνος άμεσου ελέγχου της κατάστασης του υπολογιστή κατά τον χρόνο εκτέλεσης ενός λογισμικού από τον προγραμματιστή του. Σε ορισμένες κατηγορίες προβλημάτων ωστόσο συνιστούν την πλέον βέλτιστη προσέγγιση, τουλάχιστον από τη σκοπιά της ευκολίας προγραμματισμού, αποσφαλμάτωσης και κατανόησης του πηγαίου κώδικα, αφού η εκφραστική ισχύς τους είναι υψηλή και επιτρέπουν την επίτευξη πολύπλοκων λειτουργιών από λιτούς και κομψούς κώδικες.
        Ένα βασικό χαρακτηριστικό των δηλωτικών γλωσσών είναι ότι απαγορεύουν ή αποθαρρύνουν τις διαδικασίες με παρενέργειες: διαδικασίες αμέσως μετά τον τερματισμό των οποίων η κατάσταση του προγράμματος και του υπολογιστή έχει τροποποιηθεί, σε σχέση με την κατάσταση αμέσως πριν την κλήση τους (π.χ. έχουν ανατεθεί νέες τιμές σε μεταβλητές του κύριου / εξωτερικού προγράμματος). Έτσι, ιδανικά, σε μια δηλωτική γλώσσα η μόνη «ορατή» λειτουργία μίας διαδικασίας είναι να επιστρέφει μία τιμή όταν τερματίζεται η κλήση της και δίνεται ο έλεγχος του επεξεργαστή πίσω στο κύριο πρόγραμμα. Αυτό το χαρακτηριστικό επιτρέπει στον διερμηνέα να συντάσσει διαφανώς, «πρωτοβουλιακά» και σε χρόνο εκτέλεσης, με βάση κανόνες ορισμένους από τους κατασκευαστές του, τα αλγοριθμικά βήματα τα οποία υλοποιούν μία διαδικασία. Η έλλειψη παρενεργειών και ο ντετερμινισμός η ιδιότητα μίας διαδικασίας να επιστρέφει πάντα την ίδια τιμή για τα ίδια ορίσματα , φαινόμενα από κοινού ονομαζόμενα αναφορική διαφάνεια καθώς επιτρέπουν την αντικατάσταση μίας κλήσης διαδικασίας με την τιμή επιστροφής της χωρίς να αλλοιώνονται οι επιτελούμενοι υπολογισμοί και τα αποτελέσματα εξόδου του προγράμματος, καθιστούν τον προγραμματισμό σε δηλωτικές γλώσσες να μοιάζει πιο πολύ με συγγραφή μαθηματικής απόδειξης, όπου τα βασικά αξιώματα των μαθηματικών δεν παραβιάζονται ποτέ και ο τελεστής ανάθεσης έχει μικρό μόνο ρόλο. Έτσι καθίσταται πολύ ευκολότερη και κομψότερη η αναλυτική απόδειξη της ορθής λειτουργίας ενός κώδικα σε δηλωτική γλώσσα, σε σχέση με το προστακτικό του ανάλογο.
        Οι κυριότερες υποκατηγορίες του δηλωτικού προγραμματισμού είναι ο συναρτησιακός (functional programming) και ο λογικός (logic programming). Οι συναρτησιακές γλώσσες ωθούν τον προγραμματιστή να αντιλαμβάνεται τα περισσότερα στοιχειώδη συστατικά (τελεστές, διαδικασίες κλπ) του υπό ανάπτυξη προγράμματος ως μαθηματικές συναρτήσεις, το ολικό πρόγραμμα ως σύνθεσή τους και τις αλγοριθμικές δομές επανάληψης ως αναδρομικές κλήσεις τους. Οι συναρτήσεις απεικονίζουν άμεσα τα ορίσματα εισόδου τους στις τιμές εξόδου τους, χωρίς να στηρίζονται σε παρενέργειες, ενώ φυσικά πάντα επιστρέφουν μία τιμή. Ενώ οι προστακτικές γλώσσες υψηλού επιπέδου, όπως και οι γλώσσες μηχανής των πραγματικών επεξεργαστών, θεμελιώνονται μαθηματικά στις Μηχανές Turing και κάθε πηγαίος κώδικας αναπτυγμένος σ' αυτές μοιάζει χονδρικά με πρόγραμμα μίας Μηχανής Turing Τυχαίας Προσπέλασης, οι συναρτησιακές γλώσσες θεμελιώνονται στο ισοδύναμο υπολογιστικό μοντέλο του λογισμού λ. Σε κάθε περίπτωση βεβαίως, ο μεταφρασμένος κώδικας τον οποίον παράγουν οι μεταγλωττιστές και οι διερμηνείς κάθε τύπου γλώσσας, είναι τελικά το πρόγραμμα μίας επεκταμένης Μηχανής Turing Τυχαίας Προσπέλασης, αφού όπως έχει ήδη αναφερθεί τα ποικίλα προγραμματιστικά παραδείγματα και οι διακρίσεις μεταξύ τους υφίστανται μόνο σε πηγαίο επίπεδο.
        Ο λογικός προγραμματισμός βασίζεται στην τυπική μαθηματική λογική και αναγκάζει τους προγραμματιστές να αντιλαμβάνονται τον υπό ανάπτυξη κώδικα ως περιγραφή ενός «θεωρήματος» για το οποίο ζητείται «απόδειξη». Ο διερμηνέας αναλαμβάνει να φέρει εις πέρας αυτή την απόδειξη κατά την εκτέλεση του προγράμματος, επιτελώντας έτσι τον ζητούμενο υπολογισμό με βάση τους κανόνες της κατηγορηματικής λογικής. Ο προγραμματιστής δίνει τα δεδομένα εισόδου ως «αξιώματα» του εν λόγω τυπικού συστήματος, αλλά παρέχει επίσης κατά τη συγγραφή του κώδικα και συμπερασματικούς κανόνες πέρα από τους βασικούς της κατηγορηματικής λογικής ελέγχοντας έτσι σε κάποιον βαθμό τη στρατηγική απόδειξης. Αν και οι λογικές γλώσσες έχουν θεωρητικά εκφραστική ισχύ ισοδύναμη των Μηχανών Turing (Turing-πλήρεις), επομένως μπορεί να συγγραφεί σ' αυτές κώδικας που να επιτελεί κάθε δυνατό υπολογισμό υπό επαρκείς προϋποθέσεις, οι χρήσεις αυτού του παραδείγματος είναι στην πράξη περιορισμένες. Τέλος, ως δηλωτικές μπορούν επίσης να θεωρηθούν και ορισμένες εξειδικευμένες γλώσσες οι οποίες ίσως και να μην είναι Turing-πλήρεις, έχουν επομένως δυνατότητες περιοριζόμενες από το πεδίο εφαρμογής τους: π.χ. γλώσσες ερωτημάτων με διερμηνείς ενσωματωμένους σε προγράμματα διαχείρισης βάσεων δεδομένων.
        Βεβαίως, είναι απολύτως εφικτό και συνηθισμένο μία γλώσσα να υποστηρίζει ταυτοχρόνως πολλαπλά προγραμματιστικά παραδείγματα και να παρέχει μεγάλη γκάμα συντακτικών δομών προς αυτό τον σκοπό. Τότε, κατά σύμβαση, η γλώσσα χαρακτηρίζεται με βάση το κυριότερο παράδειγμα για το οποίο σχεδιάστηκε, αν και είναι εύκολη η αξιοποίησή της για τη συγγραφή κώδικα άλλου παραδείγματος. Ως αποτέλεσμα, επί παραδείγματι, δεν είναι σπάνιο φαινόμενο η ύπαρξη συναρτησιακών γλωσσών προγραμματισμού οι οποίες επιτρέπουν την ύπαρξη διαδικασιών με παρενέργειες.


    ΙΣΤΟΡΙΚΗ ΕΞΕΛΙΞΗ ΤΩΝ ΓΛΩΣΣΩΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ 
       Στην πορεία της Ιστορίας, παρά τις σημαντικές εξελίξεις στη μελέτη των μαθηματικών σε πολλαπλούς τόπους και εποχές, δεν καθιερώθηκαν προτυποποιημένες φορμαλιστικές σημειογραφίες περιγραφής και αναπαράστασης αλγορίθμων πριν από τον 20ο μ.Χ. αιώνα. Δύο περιορισμένα αντιπαραδείγματα μπορούν να ανιχνευθούν μόνο στον αρχαίο σημιτικό πολιτισμό των Βαβυλώνιων και στα σχέδια της Αναλυτικής Μηχανής (1837 μ.Χ.), του Βρετανού μαθηματικού και εφευρέτη Τσαρλς Μπάμπατζ (1791 - 1871). Ο Βαβυλώνιοι, στις αρχές της δεύτερης χιλιετίας π.Χ., είχαν αναπτύξει μία πολύ στοιχειώδη αλλά τυποποιημένη σημειογραφία για την περιγραφή αλγορίθμων, εγγύτατη βεβαίως στη φυσική τους γλώσσα και απομακρυσμένη από τις σύγχρονες τυπικές γλώσσες. Περισσότερα από 1500 έτη μετά, ο Έλληνας μαθηματικός της ελληνιστικής εποχής Ευκλείδης, από την Αλεξάνδρεια της Αιγύπτου και με γιγάντια συνεισφορά στη γεωμετρία, περιέγραψε έναν από τους παλαιότερους καταγεγραμμένους αλγορίθμους για την εύρεση του μέγιστου κοινού διαιρέτη δύο αριθμών απλώς σε φυσική γλώσσα.
       Περί τα μέσα του 19ου μ.Χ. αιώνα ο Μπάμπατζ, με στόχο τη διευκόλυνση της εκτέλεσης βασικών μαθηματικών πράξεων και υπολογισμών, είχε σχεδιάσει έναν μηχανικό ψηφιακό, προγραμματιζόμενο υπολογιστή ικανό να εκτελέσει κάθε αλγόριθμο, περίπου έναν αιώνα πριν από τα ανάλογα μαθηματικά ευρήματα της θεωρίας υπολογισμού και την κατασκευή του πρώτου πραγματικού ψηφιακού υπολογιστή. Βεβαίως δεν γνώριζε πως η Αναλυτική Μηχανή του αν ποτέ υλοποιούνταν ήταν υπολογιστικά ισοδύναμη με Καθολική Μηχανή Turing! Προγραμματιζόταν σε μία τυποποιημένη σημειογραφία πολύ παρόμοια με αυτή των συμβολικών γλωσσών των σημερινών επεξεργαστών, ενώ αξιοποιούσε ένα δεκαδικό αριθμητικό αλφάβητο. Η Άντα Μπάιρον (1815 - 1852), κόρη του Βρετανού ποιητή Λόρδου Βύρωνα, συνέγραψε προγράμματα για την Αναλυτική Μηχανή και, ως αποτέλεσμα, σήμερα θεωρείται ιστορικά ο πρώτος προγραμματιστής λογισμικού!
       Ύστερα από έναν αιώνα, θυελλώδεις εξελίξεις σημειώθηκαν στο ζήτημα των γλωσσών προγραμματισμού μέσα σε μόνο μία εικοσαετία. Η μαθηματική έρευνα της δεκαετίας του 1930 επί του υπολογισμού έδωσε ως αποτέλεσμα θεωρητικούς φορμαλισμούς διατύπωσης αλγορίθμων όπως η Μηχανή Turing και ο λογισμός λ, ενώ ταυτοχρόνως τυποποίησε με αυστηρό μαθηματικό τρόπο τις ίδιες τις έννοιες του αλγορίθμου και του υπολογισμού, καταδεικνύοντας τα όριά τους μέσω της απόδειξης της ύπαρξης μη επιλύσιμων υπολογιστικών προβλημάτων. Στη συνέχεια, η πραγματική κατασκευή αρχικά ηλεκτρομηχανικών (1941 ο Ζ3 του Γερμανού πολιτικού μηχανικού Κόνραντ Τσούζε) και κατόπιν ηλεκτρονικών (1944 ο COLOSSUS MARK II της βρετανικής κυβέρνησης) ψηφιακών, καθολικών υπολογιστικών συσκευών, κατά τη δεκαετία του 1940 και εν μέσω του Β' Παγκοσμίου Πολέμου, ώθησε περαιτέρω τις εξελίξεις οδηγώντας στην εμφάνιση συμβολικών γλωσσών χαμηλού επιπέδου με άμεση τεχνολογική εφαρμογή! Το 1948 ο Κόνραντ Τσούζε περιέγραψε σε μία δημοσίευσή του μία γλώσσα προγραμματισμού υψηλού επιπέδου ονόματι PLANKALKUL, αλλά η εργασία του αγνοήθηκε. Ο προγραμματισμός συνέχιζε να γίνεται σε συμβολική γλώσσα, διευρυμένη εκδοχή του φορμαλισμού των Μηχανών Turing Τυχαίας Προσπέλασης, μέχρι τα μέσα της δεκαετίας του 1950.
       Το 1954 μία ομάδα επιστημόνων στις ΗΠΑ υπό την αιγίδα της εταιρείας IBM εκκίνησε τον σχεδιασμό της διαδικαστικής γλώσσας υψηλού επιπέδου FORTRAN (= «FORMULA TRANSLATOR») και την υλοποίηση ενός μεταγλωττιστή τελείωσαν το έργο τους το 1957. Το κύριο ζήτημα το οποίο τους απασχολούσε δεν ήταν τόσο η διευκόλυνση των προγραμματιστών, όσο η διασφάλιση υψηλών επιδόσεων στα παραγόμενα προγράμματα και η μείωση των σφαλμάτων του πηγαίου κώδικα. Ως το 1960 οι δυνατότητες της γλώσσας είχαν επεκταθεί και, λόγω της επιρροής της IBM, η FORTRAN καθιερώθηκε γρήγορα ως η βέλτιστη επιλογή για μαθηματικά προγράμματα και υλοποίηση αριθμητικών αλγορίθμων. Το 1958 ο Τζον Μακάρθι (John McCarthy, 1927 - 2011), Αμερικανός μαθηματικός και πρωτοπόρος επιστήμονας υπολογιστών, εφηύρε τη LISP (= «LIST PROCESSING»): την πρώτη συναρτησιακή γλώσσα υψηλού επιπέδου η οποία επρόκειτο να διαδραματίσει πολύ σημαντικό ρόλο στο γνωστικό πεδίο της τεχνητής νοημοσύνης κατά τις επόμενες δύο δεκαετίες. Το 1959, με πρωτοβουλία του Υπουργείου Αμύνης των ΗΠΑ, σχεδιάστηκε η διαδικαστική γλώσσα COBOL (= «COMMON BUSINESS-ORIENTED LANGUAGE»), έχοντας ως αφετηρία επιστημονικές συνεισφορές της Αμερικανίδας μαθηματικού Γκρέις Χόπερ (1906 - 1992). Η Χόπερ είχε κατασκευάσει τον πρώτο μεταγλωττιστή, το 1952, και είχε επινοήσει τον δημοφιλή όρο «bug» (= κοριός) για την περιγραφή σφαλμάτων σε κώδικες λογισμικού. Στόχος της COBOL ήταν η διευκόλυνση της ανάπτυξης επιχειρηματικών εφαρμογών επεξεργασίας δεδομένων και όχι εξεζητημένων αλγορίθμων ή μαθηματικών μεθόδων. Εισήγαγε την έννοια των μη μεταφραζόμενων σχολίων στον πηγαίο κώδικα, για τη βελτίωση της αναγνωσιμότητάς του, και επέφερε βελτιώσεις στις αλγοριθμικές δομές επιλογής.
       Το μεγαλύτερο εξελικτικό βήμα όμως των γλωσσών προγραμματισμού επήλθε με την ALGOL 60, αναπτυγμένη κατά την περίοδο 1960 - '63 από τη διεθνή ακαδημαϊκή κοινότητα της επιστήμης υπολογιστών. Παρά τη μικρή πρακτική εφαρμογή και εξάπλωσή της πέραν των ερευνητών της πληροφορικής, η ALGOL 60 επηρέασε τον χώρο όσο καμιά άλλη γλώσσα υψηλού επιπέδου, εισάγοντας και καθιερώνοντας τα περισσότερα χαρακτηριστικά του δομημένου προγραμματιστικού παραδείγματος. Για τις επόμενες τρεις δεκαετίες η δομή του ψευδοκώδικα των αλγορίθμων στις περισσότερες επιστημονικές δημοσιεύσεις, καθόλου τυχαία, θα προσομοιάζει στη σύνταξη της ALGOL 60, ενώ η επιρροή της στον σχεδιασμό νέων και βελτιωμένων γλωσσών προγραμματισμού κατά τη δεκαετία του 1960 υπήρξε αξιοσημείωτη. Η ALGOL 60 καινοτόμησε στην υποστήριξη δομημένων μπλοκ κώδικα με παραγραφοποίηση και εμφανή όρια, εμφωλευμένων διαδικασιών, αναδρομικών κλήσεων και παροχής ευρύτερης ελευθερίας στον προγραμματιστή όσον αφορά τους κενούς («λευκούς») χαρακτήρες στον πηγαίο κώδικα (κατ' αντιδιαστολή, οι παλαιότερες γλώσσες απαιτούσαν κάθε πηγαία γραμμή να διαμερίζεται σε σταθερά προκαθορισμένα πεδία). Σημαντικότερη ίσως όμως συνεισφορά της ALGOL 60 ήταν η επινόηση και καθιέρωση του τυποποιημένου μετασυντακτικού συμβολισμού BNF για την περιγραφή της ίδιας της γλώσσας, ικανού να αναπαραστήσει κάθε γραμματική χωρίς συμφραζόμενα.
       Ένα από τα πιο σημαντικά αποτελέσματα της έρευνας η οποία οδήγησε στην καθιέρωση του δομημένου προγραμματισμού ήταν η ανάπτυξη της γλώσσας PASCAL, από τον Νίκλαους Βιρτ (Niklaus Wirth) το 1971. Ο Βιρτ είχε ήδη δοκιμάσει να κατασκευάσει βελτιωμένες παραλλαγές της ALGOL 60, μα η PASCAL κατέληξε το πιο επηρεαστικό του δημιούργημα και γρήγορα εκθρόνισε τη «μητέρα» της ως προτιμώμενη γλώσσα διδασκαλίας προγραμματισμού Η/Υ στα περισσότερα πανεπιστήμια. Υποστήριζε πρόσθετες δομές επιλογής και επανάληψης, καθώς και τύπους δεδομένων οριζόμενους κατά περίπτωση από τον προγραμματιστή, ενώ οι αρχικοί μεταγλωττιστές της παρήγαγαν αποδοτικό κώδικα. Μ' αυτήν, το δομημένο παράδειγμα ενισχύθηκε, τυποποιήθηκε και απέδειξε την ισχύ του, έχοντας αποκτήσει πλέον ένα αναγνωρίσιμο σύνολο χαρακτηριστικών. 'Ολο και περισσότερες διαδικαστικές γλώσσες υιοθετούσαν στοιχεία ώστε να υποστηρίζουν δομημένο προγραμματισμό σύντομα οι όροι «διαδικαστικός» και «δομημένος» σχεδόν ταυτίστηκαν.
        Εν τω μεταξύ, το 1969 στα εργαστήρια της εταιρείας Bell κατασκευάστηκε η γλώσσα δομημένου προγραμματισμού C (από τους Ντένις Ρίτσι και Μπράιαν Κέρνιγχαν) και ένας πρότυπος μεταγλωττιστής της, μαζί με συνοδευτικές βιβλιοθήκες. Η γλώσσα αποτελούσε διάδοχο του δοκιμαστικού προγόνου της, ονόματι B. Στόχος ήταν να γραφεί σε αυτήν – αντί για συμβολική γλώσσα χαμηλού επιπέδου, όπως συνηθιζόταν – το νέο πολυχρηστικό λειτουργικό σύστημα της εταιρείας ονόματι UNIX, διάδοχος του προγενέστερου, καινοτόμου αλλά προβληματικού MULTICS. Επικεφαλείς της ανάπτυξης του αρχικού UNIX ήταν ο Ρίτσι, ο Κέρνιγχαν και ο Κεν Τόμπσον: η εκ νέου συγγραφή του ΛΣ σε C έγινε τελικά πραγματικότητα το 1972. Εφόσον ο μεταγλωττιστής και οι βιβλιοθήκες της C είχαν γραφεί σε πολλαπλές εκδοχές για να υποστηρίζουν υπολογιστές διαφορετικής αρχιτεκτονικής, το UNIX ήταν πλέον δυνατόν να μεταφερθεί σε εκδόσεις για μεγάλη ποικιλία υπολογιστών με μία απλή επαναμεταγλώττιση του πηγαίου του κώδικα!
       Τόσο η C όσο και το UNIX, στενά συνυφασμένες έννοιες αρχικά, εξαπλώθηκαν πολύ γρήγορα σε ποικιλία παραλλαγών, καθώς η διάθεσή τους ήταν εύκολη ή δωρεάν για μεγάλο χρονικό διάστημα, η φορητότητά τους μεταξύ διαφορετικών υπολογιστικών αρχιτεκτονικών απαράμιλλη και οι δυνατότητές τους πολύ μεγάλες. Οι μεταγλωττιστές της C παρήγαγαν εξαιρετικά αποδοτικό κώδικα, η γλώσσα παρείχε στον προγραμματιστή πολύ υψηλό βαθμό ελέγχου επί του πραγματικού υλικού (γεγονός το οποίο της χάρισε το προσωνύμιο «συμβολική γλώσσα υψηλού επιπέδου») και δεδομένης της συνύφανσής της με το ΛΣ έμοιαζε η πλέον κατάλληλη επιλογή για τη συγγραφή λογισμικού συστήματος. Ως το 1980, η C επικρατούσε πλέον σ' αυτόν τον ρόλο, ενώ η PASCAL είχε μεγάλη απήχηση στην ανάπτυξη εφαρμογών και στη διδασκαλία. Σε εξειδικευμένες περιπτώσεις βεβαίως, η FORTRAN, η COBOL και η LISP συνέχιζαν να αξιοποιούνται εκτενώς.
       Τρεις παράλληλες εξελίξεις της ίδιας εποχής, στον απόηχο της ALGOL 60, πρέπει να αναφερθούν εδώ συνοπτικά. Το 1965 η IBM αποφάσισε να συνοδεύσει την κυκλοφορία της καινοτόμου οικογένειας υπολογιστών SYSTEM / 360 με τη διάθεση ενός νέου λειτουργικού συστήματος αλλά και μίας νέας, δομημένης γλώσσας προγραμματισμού για την υποστήριξή τους. Έτσι ορίστηκαν οι προδιαγραφές και κατασκευάστηκε ο πρώτος μεταγλωττιστής της γλώσσας PL / I, σχεδιασμένης να αντικαταστήσει και τη FORTRAN και την COBOL μέσω ενός ευέλικτου συνόλου χαρακτηριστικών κατάλληλου για την ανάπτυξη εφαρμογών πολλαπλών διαφορετικών τύπων. Αν και εν πολλοίς απέτυχε στους στόχους της και η χρήση της δεν εξαπλώθηκε όσο αναμενόταν, η PL / I είναι σημαντική διότι εισήγαγε την έννοια του χειρισμού εξαιρέσεων: τη δυνατότητα ο προγραμματιστής να ορίσει περιστάσεις λαθών κατά τον χρόνο εκτέλεσης (εξαιρέσεις) όπου αυτομάτως ο έλεγχος του επεξεργαστή μεταβιβάζεται σε ειδικές, αφιερωμένες στον χειρισμό των συγκεκριμένων εξαιρέσεων διαδικασίες και στη συνέχεια επιστρέφει στην εντολή του προγράμματος αμέσως μετά από όποια προκάλεσε το λάθος.
       Δεύτερη σημαντική εξέλιξη ήταν η εμφάνιση του λογικού προγραμματιστικού παραδείγματος, το οποίο καθιερώθηκε με την επινόηση της γλώσσας PROLOG στη Γαλλία του 1972. Η PROLOG έδωσε νέα ώθηση στη συμβολική τεχνητή νοημοσύνη, αλλά απέτυχε να εξαπλωθεί σε μεγαλύτερο εύρος εφαρμογών.  Νωρίτερα είχε ήδη εφευρεθεί, ως επέκταση της ALGOL 60, η γλώσσα SIMULA 67 και μαζί της το αντικειμενοστρεφές παράδειγμα, σε μία προσπάθεια επίτευξης μεγαλύτερου βαθμού αφαίρεσης στα δεδομένα, όπως οι διαδικασίες πετύχαιναν στους αλγορίθμους. Η κατασκευασμένη στη Νορβηγία SIMULA 67 ήταν προσανατολισμένη στην εκτέλεση επιστημονικών προσομοιώσεων του πραγματικού κόσμου και δεν γνώρισε ευρύτερη εξάπλωση, οι έννοιές της όμως μεταδόθηκαν στην ανάπτυξη της κατοπινής SMALLTALK: της γλώσσας που εισήγαγε τον όρο αντικειμενοστρεφής προγραμματισμός. Η SMALLTALK αναπτύχθηκε από τον ερευνητή Άλαν Κέι της εταιρείας Xerox στο πλαίσιο μίας εργασίας με στόχο τη δημιουργία ενός χρήσιμου, αξιόπιστου και εύχρηστου ατομικού υπολογιστή. Το ερευνητικό κέντρο όπου επινοήθηκε η γλώσσα, το Xerox PARC στο Πάλο Άλτο των ΗΠΑ, καθόλη τη δεκαετία του 1970 συνεισέφερε τα μέγιστα στην εξέλιξη της πληροφορικής, με πολλαπλές εξαιρετικά επηρεαστικές εφευρέσεις. Όταν η τελική έκδοση της SMALLTALK έγινε διαθέσιμη το 1980, η έρευνα για την αντικατάσταση του δομημένου προγραμματισμού με ένα πιο σύγχρονο παράδειγμα ήταν ήδη εν εξελίξει. Στη γλώσσα αυτή, όλοι οι τύποι δεδομένων ήταν «κλάσεις» δεν υπήρχαν συνήθεις δομές δεδομένων παρά μόνο αντικείμενα.
       Την ίδια περίπου εποχή, και επίσης με επιρροές από τη SIMULA 67, ολοκληρωνόταν η ανάπτυξη της C++ ως μίας ισχυρής επέκτασης της δημοφιλούς γλώσσας προγραμματισμού C στην οποία είχαν «μεταμοσχευθεί» αντικειμενοστρεφή χαρακτηριστικά. Η επιρροή της C++ καθ' όλη τη δεκαετία του 1980 υπήρξε καταλυτική, με αποτέλεσμα τη σταδιακή κυκλοφορία αντικειμενοστρεφών εκδοχών παλαιότερων δομημένων γλωσσών προγραμματισμού και την ωρίμανση των διαφορετικών παραδειγμάτων. Ταυτόχρονα, η εξέλιξη της τεχνολογίας των μεταγλωττιστών και η μεγάλη βελτίωση των επιδόσεων του υλικού οδηγούσε αυτομάτως στην ταχύτερη εκτέλεση αποδοτικότερων προγραμμάτων, με αποτέλεσμα να μειωθεί η σημασία της εξασφάλισης παραγωγής πολύ αποδοτικού δυαδικού κώδικα κατά τον σχεδιασμό νέων γλωσσών και να αρχίσει να δίνεται περισσότερη έμφαση στη διασφάλιση της διευκόλυνσης του προγραμματιστή υψηλού επιπέδου. Στις αρχές της δεκαετίας του '90, η βαθμιαία καθιέρωση στους μικροϋπολογιστές των γραφικών διασυνδέσεων χρήστη (GUI) και η επίδραση της C++ οδήγησαν στην επικράτηση της αντικειμενοστρέφειας ως κύριου προγραμματιστικού παραδείγματος.
       Η εισαγωγή της JAVA, από την εταιρεία Sun το 1995, μίας επιτυχημένης, πλήρως αντικειμενοστρεφούς γλώσσας η οποία έμοιαζε συντακτικά με απλοποιημένη εκδοχή της C++ και προσέφερε πρωτοποριακές για την εποχή δυνατότητες, έδωσε νέα ώθηση στον χώρο. Η JAVA είναι, υπό μία έννοια, ταυτοχρόνως διερμηνευόμενη και μεταγλωττιζόμενη ώστε να αξιοποιεί τα πλεονεκτήματα και των δύο προσεγγίσεων, εις βάρος των επιδόσεων και της δυνατότητας άμεσου ελέγχου του υλικού, ενώ παρέχει στις εφαρμογές μία πλούσια πρότυπη βιβλιοθήκη και ένα κοινό περιβάλλον εκτέλεσης, σε επίπεδο υψηλότερο του λειτουργικού συστήματος, καθιστώντας εφικτή την πλήρη φορητότητα: ο ίδιος δυαδικός κώδικας τρέχει αυτούσιος σε υπολογιστές πολλαπλών αρχιτεκτονικών, υπό την προϋπόθεση πως έχουν εγκατεστημένη μία υλοποίηση του περιβάλλοντος της JAVA!
       Την ίδια εποχή, εμφανίστηκαν άτυπες βελτιώσεις στο βασικό προγραμματιστικό παράδειγμα όπως οι αντικειμενοστρεφείς γλώσσες μοντελοποίησης ή τα σχεδιαστικά πρότυπα, με γνώμονα τη διευκόλυνση των προγραμματιστών και των σχεδιαστών λογισμικού, τη μείωση των σφαλμάτων στους πηγαίους κώδικες και τη βελτίωση της παραγωγικότητας των ομάδων ανάπτυξης. Το 2001 η εταιρεία Microsoft εστίασε την προσοχή της στο .NET, μία ανταγωνιστική της JAVA πλατφόρμα ανάπτυξης και εκτέλεσης λογισμικού, εξολοκλήρου προσανατολισμένη στην αντικειμενοστρέφεια. Ενδιαφέρον χαρακτηριστικό της είναι η πολυγλωσσικότητα, επιτρέποντας την ανάπτυξη στη γλώσσα της επιλογής του προγραμματιστή (μεταξύ τεσσάρων υποστηριζόμενων), με το αποτέλεσμα όμως να εκτελείται σε κοινή πλατφόρμα και με κοινές βιβλιοθήκες διαθέσιμες. Το .NET υποστηρίζει και δύο γλώσσες σχεδιασμένες ειδικά γι' αυτό: την (στηριγμένη στη C++ και στη JAVA) αντικειμενοστρεφή C# και τη (στηριγμένη στην παλαιότερη γλώσσα ML) συναρτησιακή F#.


    <Β>ΙΣΤΟΡΙΑ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΑΡΑΔΕΙΓΜΑ STRUCTURED PARADIGM ΜΕΤΑΓΛΩΤΤΙΣΤΗΣ ΣΥΝΔΕΤΗΣ LINKER COMPILER ΔΥΝΑΜΙΚΕΣ C C++ JAVA LISP FORTRAN COBOL ALGOL PASCAL SMALLTALK SIMULA ΒΙΒΛΙΟΘΗΚΕΣ ΛΟΓΙΣΜΙΚΟ ΣΥΣΤΗΜΑΤΟΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ