Περίληψη
Αυτό το μάθημα εξηγεί τι είναι ένα πρόγραμμα και τι κάνει ένας μεταγλωττιστής: η μηχανή εκτελεί μόνο στοιχειώδεις πράξεις πάνω σε αριθμούς στη μνήμη, και ο πηγαίος κώδικας πρέπει να μεταφραστεί σε κώδικα μηχανής πριν εκτελεστεί. Διατρέχει, με ένα πρόγραμμα δύο αρχείων, τα τρία στάδια αυτής της μετάφρασης στη C++ (προεπεξεργασία, μεταγλώττιση και σύνδεση), και διακρίνει ό,τι συμβαίνει κατά τη μεταγλώττιση από ό,τι συμβαίνει κατά την εκτέλεση, με ένα σφάλμα κάθε είδους. Συγκρίνει τις μεταγλωττιζόμενες γλώσσες με τις διερμηνευόμενες, συνοψίζει την ιστορία της C++ έως τα πρότυπα C++23 και C++26, και διευκρινίζει ποια C++ διδάσκει αυτός ο κύκλος μαθημάτων.
Μαθησιακοί στόχοι
- Να εξηγείται, με ένα σχήμα, η διαδρομή ενός αρχείου πηγαίου κώδικα έως ένα εκτελέσιμο αρχείο: προεπεξεργασία, μεταγλώττιση και σύνδεση, με ό,τι εισέρχεται και ό,τι εξέρχεται από κάθε στάδιο.
- Να κατατάσσεται ένα συμβάν ως ζήτημα της μεταγλώττισης, της σύνδεσης ή της εκτέλεσης, όπως ένα συντακτικό σφάλμα, η έλλειψη μιας συνάρτησης ή μια διαίρεση με το μηδέν.
- Να συγκρίνεται μια μεταγλωττιζόμενη γλώσσα με μια διερμηνευόμενη ως προς τη στιγμή κατά την οποία εντοπίζονται τα σφάλματα και ως προς ό,τι βλέπει από τη μηχανή όποιος προγραμματίζει.
- Να τοποθετούνται στον χρόνο τα πρότυπα της γλώσσας και να εξηγείται γιατί ο κύκλος χρησιμοποιεί τη C++23.
Τι είναι ένα πρόγραμμα
Ένα πρόγραμμα είναι μια ακολουθία οδηγιών που μια μηχανή μπορεί να εκτελέσει για να μετασχηματίσει κάποια δεδομένα σε κάποια αποτελέσματα. Στο προηγούμενο μάθημα, Από το πρόβλημα στον αλγόριθμο, είδαμε ότι πριν από το πρόγραμμα υπάρχει ο αλγόριθμος, η μέθοδος που λύνει το πρόβλημα, γραμμένη ώστε να την ακολουθεί ένας άνθρωπος. Το πρόγραμμα είναι η ίδια μέθοδος γραμμένη για μια μηχανή, η οποία δεν καταλαβαίνει φράσεις ούτε προθέσεις, αλλά στοιχειώδεις εντολές: να αντιγράψει έναν αριθμό από μια θέση της μνήμης σε άλλη, να προσθέσει δύο αριθμούς, να τους συγκρίνει, να μεταβεί σε άλλη οδηγία ανάλογα με το αποτέλεσμα.
Η μνήμη του υπολογιστή είναι μια μακριά σειρά από αριθμημένες θέσεις, καθεμιά με έναν αριθμό από 0 έως 255 (ένα byte). Ό,τι χειρίζεται η μηχανή είναι κωδικοποιημένο εκεί ως αριθμοί: τα δεδομένα και επίσης οι ίδιες οι οδηγίες. Αν αυτό ισχύει, ένα εκτελέσιμο πρόγραμμα είναι μια ακολουθία αριθμών που ο επεξεργαστής ερμηνεύει ως εντολές, ο κώδικας μηχανής, και εξαρτάται από τον επεξεργαστή: οι επεξεργαστές της οικογένειας x86-64, συνηθισμένοι στους επιτραπέζιους υπολογιστές, και οι ARM, συνηθισμένοι στα τηλέφωνα και στους πρόσφατους Mac, δεν καταλαβαίνουν τους ίδιους αριθμούς.
Κανείς σήμερα δεν γράφει σε κώδικα μηχανής. Γράφουμε σε μια γλώσσα υψηλού επιπέδου, όπως η C++, της οποίας οι οδηγίες μοιάζουν με τον μαθηματικό συμβολισμό, σε ένα αρχείο κειμένου που ονομάζεται πηγαίος κώδικας (ή απλώς πηγή). Από αυτό έπεται η ανάγκη ενός μεταφραστή που παράγει, από την πηγή, τον ισοδύναμο κώδικα μηχανής: στη C++, ο μεταγλωττιστής.
Αυτό είναι ένα πλήρες πρόγραμμα σε C++. Δεν χρειάζεται να το καταλάβετε ακόμη: καθεμιά από τις γραμμές του θα εξηγηθεί στο μάθημα 1.5. Αρκεί να δείτε ότι είναι κείμενο, ότι μπορεί να διαβαστεί, και ότι από κάτω εμφανίζεται ό,τι έγραψε όταν εκτελέστηκε.
// Θα εξηγηθεί γραμμή προς γραμμή στο μάθημα 1.5.#include <print>int main(){ std::println("Γεια σου, κόσμε"); std::println("2 + 3 = {}", 2 + 3);}Γεια σου, κόσμε2 + 3 = 5Για να δούμε το άλλο άκρο της μετάφρασης, ας εξετάσουμε μια συνάρτηση που απλώς προσθέτει δύο ακεραίους (οι συναρτήσεις θα μελετηθούν στην ενότητα 5). Δεν είναι πλήρες πρόγραμμα, επειδή του λείπει η main, το σημείο από όπου αρχίζει η εκτέλεση, αλλά ο μεταγλωττιστής μπορεί να τη μεταφράσει και μόνη της.
int add(int a, int b){ return a + b;}Το πρόγραμμα objdump δείχνει τον κώδικα μηχανής που παρήγαγε γι’ αυτήν ο GCC 15 σε έναν υπολογιστή x86-64 με Linux: σε κάθε γραμμή, τη θέση της οδηγίας, τα bytes της σε δεκαεξαδική μορφή και το αναγνώσιμο όνομά της.
$ g++ -std=c++23 -O1 -c add.cpp$ objdump -d add.o0000000000000000 <_Z3addii>: 0: f3 0f 1e fa endbr64 4: 8d 04 37 lea (%rdi,%rsi,1),%eax 7: c3 retΗ ακέραια πρόσθεση περιορίστηκε σε οκτώ bytes. Η πρώτη οδηγία, endbr64, είναι ένα σημάδι ασφαλείας που δεν υπολογίζει τίποτα· η δεύτερη, lea, προσθέτει τους δύο αριθμούς που η συνάρτηση έλαβε σε δύο καταχωρητές του επεξεργαστή (%rdi και %rsi) και αφήνει το αποτέλεσμα σε έναν τρίτο (%eax)· η τρίτη, ret, επιστρέφει στο σημείο από όπου κλήθηκε η συνάρτηση. Το όνομα _Z3addii είναι ο τρόπος με τον οποίο ο μεταγλωττιστής κωδικοποιεί τη «συνάρτηση add με δύο παραμέτρους int».
Δύο παρατηρήσεις προκύπτουν από το παράδειγμα. Πρώτη: ο κώδικας μηχανής δεν διατηρεί τα ονόματα a και b, ούτε την εσοχή, ούτε τα σχόλια· όλα αυτά υπήρχαν για όποιον διαβάζει την πηγή, και ο μεταγλωττιστής τα χρησιμοποίησε για να αποφασίσει ποιες οδηγίες θα γράψει. Δεύτερη: ό,τι γράφει όποιος προγραμματίζει σε C++ μεταφράζεται σε λίγες οδηγίες και χωρίς μεσάζοντες· αυτή η εγγύτητα στη μηχανή είναι ο λόγος της αποδοτικότητας της C++ και, όπως θα φανεί στον κύκλο, και ορισμένων από τους κινδύνους της.
Φόρτωση του περιεχομένου…
Ολοκληρώθηκε
Συνδεθείτε για να αποθηκεύσετε την πρόοδό σας