next up previous contents
Next: 2.3 Το πρόγραμμα mean.c Up: 2. Προγραμματισμός στη γλώσσα Previous: 2.1 Γενικά για τη   Contents

Subsections

2.2 Το πρόγραμμα hello.c

Τηρώντας την παράδοση, αρχίζουμε περιγράφοντας ένα απλό πρόγραμμα σε C το οποίο δεν κάνει τίποτε άλλο από το να τυπώνει
Hello, world!
στην οθόνη του υπολογιστή.



   1 #include        <stdio.h>
   2 
   3 main()
   4 {
   5         printf("Hello, world!\n");
   6 }

Το αρχείο hello.c

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

2.2.1 Η διαδικασία συγγραφής και εκτέλεσης ενός προγράμματος

Προτού αναφερθούμε στο πρόγραμμα αυτό και στο πώς λειτουργεί, είναι πλέον κατάλληλη η στιγμή για να εξηγήσουμε το ποια είναι η διαδικασία την οποία ακολουθούμε για να γράψουμε ένα πρόγραμμα.

Ότι πούμε παρακάτω ισχύει στο λειτουργικό σύστημα Unix. Σε άλλα λειτουργικά συστήματα (π.χ. MS Windows) και ανάλογα με το software που χρησιμοποιείται, δηλ. ανάλογα με τον ποιόν compiler χρησιμοποιούμε, η διαδικασία μπορεί να είναι από αρκετά δαφορετική έως πολύ όμοια.

Κατ' αρχήν, το C πρόγραμμα (το κείμενο που βλέπετε παραπάνω) φτιάχνεται και αποθηκεύεται σε ένα αρχείο (file), στο οποίο δίνουμε ένα περιγραφικό όνομα και την κατάληξη2.2.c (στο συγκεκριμένο πρόγραμμα δώσαμε το όνομα hello.c, για παράδειγμα).

Το κείμενο δημιουργήθηκε χρησιμοποιώντας ένα text editor. Υπάρχουν πολλοί text editors στο Unix, με αρκετά διαφορετικά χαρακτηριστικά ο καθένας, και προτείνεται, για αρχή τουλάχιστον, να χρησιμοποιείτε τον pico, ο οποίος είναι πολύ εύχρηστος. Για να δημιουργήσετε λοιπόν το αρχείο hello.c θα ξεκινήσετε δίνοντας την εντολή (από δω και πέρα οι γραμμές που αρχίζουν με % θα παριστάνουν εντολές που δίνετε στο command line - γραμμή εντολών - του Unix):

% pico hello.c
Αφού τελειώσετε με το γράψιμο του κειμένου το αποθηκεύετε και βγαίνετε από το περιβάλλον του pico.

Αν τα κάνετε όλα σωστά υπάρχει πλέον στην περιοχή σας ένα αρχείο με όνομα hello.c. Προσέξτε γιατί στο Unix και στη C τα κεφαλαία και τα μικρά γράμματα θεωρούνται διαφορετικά, για παράδειγμα τα ονόματα hello.c και Hello.c θεωρούνται διαφορετικά από το Unix και μπορεί κάλλιστα να έχετε δυο διαφορετικά αρχεία με αυτά τα ονόματα. Για να βεβαιωθείτε ότι έχετε όντως το αρχείο στην περιοχή σας δώστε την εντολή2.3

% cat hello.c
και, αν όλα έχουν πάει καλά, θα δείτε τα περιεχόμενα του αρχείου να τυπώνονται στην οθόνη σας.

Έχοντας βεβαιωθεί πια ότι το αρχείο hello.c υπάρχει και έχει τα σωστά περιεχόμενα, μπορούμε να προχωρήσουμε στη φάση του compilation, ώστε να παραχθεί έτσι ένα εκτελέσιμο πρόγραμμα. Δώστε την εντολή2.4

% gcc hello.c
Αν δεν εκτυπωθούν error messages (αν έχετε το σωστό αρχείο δε θα εκτυπωθούν) τότε μετά από το πέρας αυτής της εντολής θα υπάρχει στην περιοχή σας ένα αρχείο με όνομα a.out, που είναι κατά παράδοση το όνομα που παίρνουν τα εκτελέσιμα αρχεία στο Unix, αν ο χρήστης δεν κάνει τον κόπο να δηλώσει ότι επιθυμεί ένα άλλο όνομα. Αν ο χρήστης θέλει το εκτελέσιμο αρχείο να μην έχει το καθιερωμένο όνομα a.out (για παράδειγμα αν θέλει να έχει παραπάνω από ένα εκτελέσιμα αρχεία στην περιοχή του) τότε μπορεί να πεί στον compiler τι όνομα να δώσει σε αυτό ως εξής:
% gcc hello.c -o hello
Αυτό φτιάχνει ένα εκτελέσιμο αρχείο με όνομα hello (είναι σύνηθες στη C το όνομα του εκτελέσιμοθ να είναι το ίδιο με το όναμα του αρχείου του προγράμματος χωρίς κατάληξη, αν πρόκειται για το Unix, ή με κατάληξη .exe στα MS Windows).

Για να βεβαιωθείτε ότι υπάρχει όντως το αρχείο a.out στην περιοχή σας δώστε την εντολή

% ls
η οποία θα τυπώσει στην οθόνη σας τα ονόματα όλων των υπαρχόντων αρχείων (ανάμεσά τους θα πρέπει να είναι τα hello.c και a.out). Η εντολή
% ls -F
θα πρέπει να τυπώσει κι ένα αστερίσκο (*) δίπλα στο a.out το οποίο υποδηλώνει ότι αυτό είναι ένα εκτελέσιμο αρχείο.

Τέλος, εκτελούμε το πρόγραμμά μας δίνοντας την εντολή

% a.out
Hello, world!
%
(Οι γραμμές παραπάνω που δεν αρχίζουν με % υποδηλώνουν το output του προγράμματος που μόλις εκτελέσαμε.)

2.2.2 Ανάλυση του hello.c

Ας αναλύσουμε τώρα το hello.c γραμμή προς γραμμή για να δούμε πως δουλεύει.

Κατ' αρχήν, στη γραμμή 1, βρίσκεται μια εντολή που απευθύνεται στον cpp, τον C preprossesor, και λέει στον cpp να τοποθετήσει τα περιεχόμενα του αρχείου stdio.h στη θέση της γραμμής #include. Το αρχείο stdio.h (standard input/output header file) δεν περιέχει κάποιο εκτελέσιμο κώδικα, αλλά κάποιες δηλώσεις σταθερών και υποπρογραμμάτων (για παράδειγμα, τι είδους παραμέτρους περιμένει να λάβει το υποπρόγραμμα printf που χρησιμοποιείται μέσα στο hello.c. Για να είμαστε ακριβείς, η πρώτη γραμμή δεν είναι απολύτως απαραίτητη για την επιτυχή μετάφραση και εκτέλεση του συγκεκριμένου προγράμματος, κι αν σβήσετε την πρώτη γραμμή και επαναλάβετε τον κύκλο μεταγλώττισης και εκτέλεσης θα δείτε πως το πρόγραμμα θα εκτελεστεί κανονικά.

Είναι όμως λάθος πρακτική να μην συμπεριλαμβάνονται τα απαραίτητα header files (αυτά που κατά παράδοση έχουν την κατάληξη .h) στο υπό μεταγλώττιση πρόγραμμα, μια και περιέχουν πληροφορίες για τα χρησιμοποιούμενα υποπρογράμματα (πληροφορίες και οδηγίες για τον compiler και όχι για τον προγραμματιστή, ο οποίος σπανίως χρειάζεται να εξετάσει τα περιεχόμενα ενός header file εκτός ίσως από αυτά που ο ίδιος έχει γράψει) που είναι πιο συχνά απαραίτητες για να δουλέψει το πρόγραμμα σωστά παρά όχι.

2.2.3 Παρένθεση: το manual στο Unix

Πώς γνωρίζαμε ποιό αρχείο να κάνουμε #include; Η πληροφορία αυτή βρίσκεται στο manual της γλώσσας, ή, για να είμαστε πιο ακριβείς, στο manual της standard library της C, μέρος της οποίας βιβλιοθήκης είναι και η συνάρτηση (συνάρτηση, υποποπρόγραμμα και υπορουτίνα είναι συνώνυμες λέξεις στη C) printf. Στο Unix το manual αυτό βρίσκεται (ή, καλύτερα, πρέπει να βρίσκεται, μια και δεν είναι όλα τα Unix συστήματα το ίδιο καλά φτιαγμένα ή, το σημαντικότερο, συντηρημένα) και σε ηλεκτρονική μορφή. Αν δώσετε την εντολή
% man 3 printf
το σύστημα θα σας δείξει μερικές σελίδες με πληροφορίες για τη συνάρτηση printf και άλλες σχετικές συναρτήσεις. Ανάμεσα στις πληροφορίες αυτές είναι και η συμβουλή να κάνετε #include το stdio.h προκειμένου να χρησιμοποιείσετε την printf.

Τι είναι ο αριθμός 3 αμέσως μετά το όνομα του προγράμματος man; Είναι το τμήμα του manual του συστήματος όπου βρίσκονται οι πληροφορίες για τη standard C library. Αν είχαμε παραλείψει τον αριθμό 3 και είχαμε απλώς γράψει man printf, το σύστημα θα μας τύπωνε πληροφορίες για το πρόγραμμα printf, που είναι ένα αυτοδύναμο πρόγραμμα που υπάρχει στο Unix και που εκτελεί μια παρόμοια δουλειά με αυτή που κάνει η συνάρτηση printf της standard C library. Και πώς θα καταλαβαίναμε τότε σε ποιο τμήμα του manual είναι η printf που μας ενδιαφέρει εμάς; Υπάρχει το option -k (από το keyword) για το πρόγραμμα man που λέει στο πρόγραμμα να τυπώσει μια γραμμή με λίγη πληροφορία για όλα τα σχετικά προγράμματα. Για παράδειγμα, στο Unix σύστημα που δουλεύω αυτή τη στιγμή ιδού το αποτέλεσμα του man -k printf:

% man -k printf
fprintf (3)          - formatted output conversion
gl_printf (3)        - write formatted output in graphic mode
printf (1)           - format and print data
printf (3)           - formatted output conversion
printftest (6)       - tests the vgagl gl_printf function
snprintf (3)         - formatted output conversion
sprintf (3)          - formatted output conversion
vfprintf (3)         - formatted output conversion
vprintf (3)          - formatted output conversion
vsnprintf (3)        - formatted output conversion
vsprintf (3)         - formatted output conversion
%
Το output έχει από μια γραμμή για κάθε τι που βρήκε το man σχετικό με τη λέξη printf. Η πρώτη λέξη είναι το όνομα της σχετικής ``σελίδας'' του manual και εντός παρενθέσεως βρίσκεται το section του manual. Προσέξτε ότι εμφανίζονται δύο printf, ένα στο section 1 κι ένα στο section 3. Κάνοντας man 1 printf και man 3 printf θα σας δείξει πληροφορίες για δύο διαφορετικά πράγματα. Αντίθετα για το vprintf που εμφανίστηκε μόνο του αρκεί να κάνει κανείς man vprintf για να πάρει όλες τις πληροφορίες που υπάρχουν.

Το συντακτικό της εντολής man μπορεί να διαφέρει από σύστημα σε σύστημα. Για παράδειγμα σε ορισμένα συστήματα της Sun χρειάζεται κανείς να γράψει man -s 3 printf αντί για man 3 printf. Δώστε απλώς

% man man
για να βεβαιωθείτε πώς περιμένει τις παραμέτρους του το δικό σας man.

2.2.4 Ανάλυση του hello.c - Συνέχεια

Πριν συνεχίσουμε την ανάλυση του προγράμματος hello.c να πούμε πως το ίδιο πρόγραμμα θα μπορούσε να είχε γραφεί και έτσι:
#include	<stdio.h>
main() { printf("Hello, world!\n"); }
Με λίγα λόγια, οι κενές γραμμές και η στοίχιση δεν επηρεάζουν το πως ο compiler αντιλαμβάνεται το πρόγραμμα και άρα είμαστε ελεύθεροι να στοιχίσουμε το κείμενο όπως εμάς εξυπηρετεί. (Οι εντολές όμως προς τον cpp , τα #include δηλ. και τα #define, που θα τα δούμε αργότερα, υπακούουν σε αρκετά αυστηρότερους κανόνες στοίχισης, και θα τα γράφουμε πάντα σε μια γραμμή το καθένα - αν δε ``χωράνε'' θα δούμε αργότερα τι θα κάνουμε - αρχίζοντας από τα αριστερά της γραμμής.)

Οι γραμμές 3-6 στο πρόγραμμα παριστάνουν την περιγραφή λειτουργίας μιας συνάρτησης (υπορουτίνα, υποπρόγραμμα). Ένα C πρόγραμμα αποτελείται από ένα σύνολο συναρτήσεων, γραμμένες συνήθως η μια μετά την άλλη (δεν επιτρέπονται, όπως στην Pascal, για παράδειγμα, οι δηλώσεις υπορουτινών μέσα σε υπορουτίνες). Από αυτές τις συναρτήσεις ακριβώς μία φέρει το όνομα main και είναι, κατά σύμβαση, η υπορουτίνα που εκτελείται πρώτη, και που είναι άρα υπεύθυνη για να ``καλέσει'' οποιαδήποτε άλλη συνάρτηση απαιτείται. Μετά το πέρας της main το πρόγραμμα έχει τελειώσει.

Στο πρόγραμμα αυτό εμφανίζονται δυο συναρτήσεις: η main και η printf. Η πρώτη από αυτές ορίζεται μέσα στο πρόγραμμα ενώ η δεύτερη όχι, είναι δηλ. η printf μια συνάρτηση βιβλιοθήκης, και ο compiler (για την ακρίβεια, ο linker2.5ή loader, όπως λέγεται στο Unix) ξέρει που θα την αναζητήσει για να συμπεριλάβει τον κώδικα για την printf στο τελικό εκτελέσιμο πρόγραμμα2.6. Η main καλείται από το λειτουργικό σύστημα όταν δώσουμε εμείς στο command line την εντολή a.out, και με τη σειρά της καλεί την printf ``περνώντας'' της, όπως λέμε, κάποιες παραμέτρους. Στη συγκεκριμένη περίπτωση η παράμετρος είναι μία, η λέξη (string) "Hello, world!\n". Και η printf καλεί κι αυτή με τη σειρά της κάποιες συναρτήσεις βιβλιοθήκης, αλλά αυτές δεν είμαστε σε θέση να τις γνωρίζουμε, και δε χρειάζεται συνήθως να τις γνωρίζουμε. Είμαστε απλοί χρήστες ενός ``μαύρου κουτιού'' που λέγεται printf και χρειάζεται να ξέρουμε μόνο τη λειτουργική του συμπεριφορά, δηλ. τι αποτέλεσμα θα έχει αν του δώσουμε το τάδε όρισμα, κι όχι το πώς είναι φτιαγμένο.

Στο πρόγραμμα αυτό δεν υπάρχουν μεταβλητές. Υπάρχει μόνο μια σταθερά, το string "Hello, world!\n". Ποιο το νόημα του περίεργου \n στο τέλος του string; Το backslash (\) παίζει ένα ειδικό ρόλο στη C, και στο Unix γενικότερα. Χρησιμοποιείται για να υποδηλώσει ότι ο επόμενος χαρακτήρας (δηλ. γράμμα) που ακολουθεί στο string δεν αντιπροσωπεύει το γράμμα το οποίο φαίνεται, αλλά κάποιο άλλο χαρακτήρα, για τον οποίο συνήθως δεν υπάρχει σύμβολο να τον γράψουμε. Έτσι στη C ο συνδυασμός \n παριστάνει το χαρακτήρα LF (line feed) ο οποίος χρησιμοποιείται για να αλλάξει γραμμή το τερματικό στο οποίο τυπώνουμε. Αν η σταθερά ήταν η "Hello, world!" (χωρίς το LF στο τέλος) τότε το output του προγράμματος θα ήταν ως εξής:

% a.out
Hello, world!%
Δε θα άλλαζε δηλαδή γραμμή το τερματικό μετά την εκτύπωση του κειμένου και το prompt του επόμενου command line θα τυπωνόταν αμέσως μετά το θαυμαστικό.

2.2.5 Παρένθεση: ο κώδικας ASCII

Υπάρχει ένας κώδικας αντιστοίχισης, ο ASCII (American Standard Code for Information Interchange), ανάμεσα στους αριθμούς από 0 έως 255 - αυτοί είναι οι αριθμοί που μπορούν να γραφούν με 8 δυαδικά ψηφία - και σε διάφορα σύμβολα, που μπορεί να υπάρχουν στο πληκτρολόγιό σας, μπορεί και όχι. Τα σύμβολα αυτά συμπεριλαμβάνουν όλα τα γράμματα του λατινικού αλφαβήτου, μικρά και κεφαλαία, σημεία στίξης, διαφόρων ειδών παρενθέσεις, και διάφορα άλλα σύμβολα που δεν έχουν κάποιο σχήμα αλλά χρησιμοποιούνται κατά σύμβαση για κάποιο συγκεκριμένο σκοπό. Υπάρχει για παράδειγμα στο Unix ένας χαρακτήρας, ο line-feed (LF) με αριθμό 10, που χρσιμοποιείται για να δηλώσει ότι έχει φτάσει το τέλος της τρέχουσας γραμμής. Έτσι όταν ένα πρόγραμμα διαβάζει ένα αρχείο και συναντήσει το χαρακτήρα LF συμπεραίνει συνήθως (αυτό πραγματικά είναι θέμα του συγκεκριμένου προγράμματος) ότι έχει επέλθει αλλαγή γραμμής και ενεργεί ανάλογα. Αν, για παράδειγμα, το πρόγραμμα αυτό είναι πρόγραμμα εκτύπωσης στον εκτυπωτή τότε, κατά πάσα πιθανότητα, θα στείλει στον εκτυπωτή εντολή να αλλάξει γραμμή εκτύπωσης προτού συνεχίσει να του στέλνει άλλους χαρακτήρες για εκτύπωση.

Για να είμαστε λίγο πιο ακριβείς, ο κώδικας ASCII μόνο αντιστοιχεί χαρακτήρες στα νούμερα από 0 έως 127 (αριθμοί που μπορούν να παρασταθούν με 7 δυαδικά ψηφία). Πολλά σύμβολα, όπως για παράδειγμα αυτά της Ελληνικής αλφαβήτου μένουν απ' έξω, και το κομμάτι από 128 έως 255 χρησιμοποιείται, μεταξύ άλλων, και για την παράσταση αλφαβήτων διαφορετικών από το λατινικό (το οποίο παρίσταται από το standard ASCII κάτω από το 128).

Μπορείτε να δείτε στον παρακάτω πίνακα τους χαρακτήρες για τα ASCII codes από 0 έως 127.

Dec Hx Oct Char                        Dec Hx Oct Char  Dec Hx Oct Char  Dec Hx Oct Char
---------------                        ---------------  ---------------  ---------------
  0  0 000 NUL (null)                   32 20 040 SPACE  64 40 100 @      96 60 140 `
  1  1 001 SOH (start of heading)       33 21 041 !      65 41 101 A      97 61 141 a
  2  2 002 STX (start of text)          34 22 042 "      66 42 102 B      98 62 142 b
  3  3 003 ETX (end of text)            35 23 043 #      67 43 103 C      99 63 143 c
  4  4 004 EOT (end of transmission)    36 24 044 $      68 44 104 D     100 64 144 d
  5  5 005 ENQ (enquiry)                37 25 045 %      69 45 105 E     101 65 145 e
  6  6 006 ACK (acknowledge)            38 26 046 &      70 46 106 F     102 66 146 f
  7  7 007 BEL (bell)                   39 27 047 '      71 47 107 G     103 67 147 g
  8  8 010 BS  (backspace)              40 28 050 (      72 48 110 H     104 68 150 h
  9  9 011 TAB (horizontal tab)         41 29 051 )      73 49 111 I     105 69 151 i
 10  A 012 LF  (NL line feed, new line) 42 2A 052 *      74 4A 112 J     106 6A 152 j
 11  B 013 VT  (vertical tab)           43 2B 053 +      75 4B 113 K     107 6B 153 k
 12  C 014 FF  (NP form feed, new page) 44 2C 054 ,      76 4C 114 L     108 6C 154 l
 13  D 015 CR  (carriage return)        45 2D 055 -      77 4D 115 M     109 6D 155 m
 14  E 016 SO  (shift out)              46 2E 056 .      78 4E 116 N     110 6E 156 n
 15  F 017 SI  (shift in)               47 2F 057 /      79 4F 117 O     111 6F 157 o
 16 10 020 DLE (data link escape)       48 30 060 0      80 50 120 P     112 70 160 p
 17 11 021 DC1 (device control 1)       49 31 061 1      81 51 121 Q     113 71 161 q
 18 12 022 DC2 (device control 2)       50 32 062 2      82 52 122 R     114 72 162 r
 19 13 023 DC3 (device control 3)       51 33 063 3      83 53 123 S     115 73 163 s
 20 14 024 DC4 (device control 4)       52 34 064 4      84 54 124 T     116 74 164 t
 21 15 025 NAK (negative acknowledge)   53 35 065 5      85 55 125 U     117 75 165 u
 22 16 026 SYN (synchronous idle)       54 36 066 6      86 56 126 V     118 76 166 v
 23 17 027 ETB (end of trans. block)    55 37 067 7      87 57 127 W     119 77 167 w
 24 18 030 CAN (cancel)                 56 38 070 8      88 58 130 X     120 78 170 x
 25 19 031 EM  (end of medium)          57 39 071 9      89 59 131 Y     121 79 171 y
 26 1A 032 SUB (substitute)             58 3A 072 :      90 5A 132 Z     122 7A 172 z
 27 1B 033 ESC (escape)                 59 3B 073 ;      91 5B 133 [     123 7B 173 {
 28 1C 034 FS  (file separator)         60 3C 074 <      92 5C 134 \     124 7C 174 |
 29 1D 035 GS  (group separator)        61 3D 075 =      93 5D 135 ]     125 7D 175 }
 30 1E 036 RS  (record separator)       62 3E 076 >      94 5E 136 ^     126 7E 176 ~
 31 1F 037 US  (unit separator)         63 3F 077 ?      95 5F 137 _     127 7F 177 DEL



Υποσημειώσεις

... κατάληξη2.2
Είναι ο κανόνας, σχεδόν ανεξάρτητα από λειτουργικό σύστημα, να χρησιμοποιείται η κατάληξη του ονόματος ενός αρχείου, δηλ. το κομμάτι του ονόματος μετά την τελευταία τελεία (αν υπάρχει), για να υποδηλώσει το είδους των περιεχομένων του αρχείου. Έτσι, π.χ., στα MS Windows, κατάληξη .doc υποδηλώνει ένα αρχείο που έχει φτιαχτεί από το MS Word πρόγραμμα, κατάληξη .exe υποδηλώνει ένα εκτελέσιμο πρόγραμμα, στο Unix κατάληξη .f δηλώνει ένα πρόγραμμα Fortran, κοκ. Είναι σημαντικό εδώ να πούμε και να τονίσουμε ότι το ράσο δεν κάνει τον παπά. Δεν μπορεί κανείς, για παράδειγμα, μετονομάζοντας ένα άσχετο αρχείο σε κατάληξη .exe να το καταστήσει εκτελέσιμο. Αυτό φυσικά εξαρτάται από το περιεχόμενο του αρχείου.
... εντολή2.3
Η εντολή cat του Unix τυπώνει τα περιεχόμενα ενός ή περισσοτέρων αρχείων στην οθόνη.

Καμία σχέση με ... γάτες. Η ονοματολογία προγραμμάτων στο Unix είναι λίγο περίεργη μερικές φορές, πέρα από το ότι είναι και κρυπτική. Σαν παράδειγμα αναφέρω το πρόγραμμα biff, το οποίο ειδοποιεί τον χρήστη κάνοντας beep και τυπώνοντας ένα μικρό μήνυμα στην οθόνη οποτεδήποτε φτάσει ένα νέο μήνυμα e-mail. Η ιστορία είναι ότι ο προγραμματιστής που έφτιαξε αυτό το πρόγραμμα, ο οποίος ζούσε στο Berkeley, CA, είχε ένα σκύλο με το ίδιο όνομα ο οποίος έιχε τη συνήθεια να γαυγίζει οποτεδήποτε ερχόταν ο ταχυδρόμος. Εξ ού το όνομα.

... εντολή2.4
Ανάλογα σε τι σύστημα δουλεύετε μπορεί να χρειαστεί η εντολή αυτή να είναι λίγο διαφορετική. Τώρα πλέον όλα σχεδόν τα Unix συστήματα είναι εφοδιασμένα με τον GNU C Compiler (gcc) (ο οποίος είναι ένας πάρα πολύ καλός, δωρεάν C compiler), αλλά αν δεν υπάρχει η εντολή gcc (αν δηλ. πάρετε μήνυμα command not found ή κάτι παρόμοιο) δοκιμάστε να γράψετε cc αντί για gcc. Σε συστήματα MS Windows αντικαταστείστε τον gcc με το όνομα του compiler που χρησιμοποιείτε (υπάρχει και ο gcc για MS Windows).
...linker2.5
Ο linker είναι ένα πρόγραμμα που δε μεταφράζει από C ή κάποια άλλη γλώσσα υψηλού επιπέδου σε γλώσσα μηχανής, αλλά παίρνει ένα σύνολο από ήδη μεταφρασμένες υπορουτίνες και τις διασυνδέει: αν υπάρχει μια ρουτίνα που καλέι π.χ. την printf θα φροντίσει ο linker να υπάρχει στο αντίστοιχο σημείο της ρουτίνας αυτής μια μεταπήδηση στη θέση μνήμης όπου αρχίζει ο κώδικας της printf. Αυτή είναι μια δουλειά που δε μπορεί να γίνει από τον compiler ο οποίος δεν έχει ιδέα του ποιές είναι όλες οι ρουτίνες που θα χρησιμοποιηθούν σε ένα πρόγραμμα.

Σε πρώτη προσέγγιση δε βλάπτει ιδιαίτερα όμως το να αγνοεί κανείς το διαχωρισμό αυτό ανάμεσα σε compiler και linker.

... πρόγραμμα2.6
Και αυτό δεν είναι τελείως ακριβές, μια και με τα λεγόμενα shared libraries, που χρησιμοποιουνται στα σύγχρονα λειτουργικά συστήματα, πολλές κοινόχρηστες υπορουτίνες δεν είναι πλέον μέρος του εκτελέσιμου προγράμματος, αλλά αναλαμβάνει το λειτουργικό σύστημα να τις παρέχει στα εκτελέσιμα προγράμματα που τις ζητούν, at run-time.

Έτσι εξοικονομείται ο χώρος που θα έπιανε, π.χ. η printf, σε όλα τα εκτελέσιμα προγράμματα που την καλούν (πολύ πιθανόν και όλα), η οποία ρουτίνα υπάρχει τώρα στο shared library μόνο. Επίσης εξοικονομείται μνήμη μια και μπορεί ανά πάσα στιγμή να τρέχουν π.χ. 10 προγράμματα που όλα καλούν την printf, και δεν υπάρχει κανένας εγγενής λόγος να υπάρχουν 10 αντίγραφα του κώδικα μηχανής της printf φορτωμένα στη μηχανή, μια και ο κώδικας αυτός είναι ένα στατικό αντικείμενο και δεν το αλλάζει το πρόγραμμα.

Ένα άλλο μεγάλο πλεονέκτημα χρήσης shared libraries vs. archive libraries (δηλ. στατικές βιβλιοθήκες) είναι το ότι δε χρειάζεται να προγράμματα εφαρμογής να αλλάξουν στο παραμικρό αν αντικατασταθεί μια ρουτίνα από ένα shared library. Φανταστείτε για παράδειγμα ότι ο προμηθευτής σας σας δίνει μια νέα standard library της C, που περιέχει μια σαφώς βελτιωμένη έκδοση της printf, χωρίς φυσικά να έχει αλλάξει το interface (δηλ. ο τρόπος με τον οποίο καλείται, το πρωτόκολλο επικοινωνίας ρουτίνας και προγράμματος που την καλεί). Τότε απλά αντικαθιστάτε την παλιά σας βιβλιοθήκη με την καινούργια και οποιαδήποτε εφαρμογή χρησιμοποιούσε την printf μέσα από το shared library την επόμενη φορά που θα τρέξει θα χρησιμοποιήσει αυτόματα την νέα printf. Κάτι τέτοιο θα ήταν αδύνατο αν κάθε πρόγραμμα που χρησιμοποιούσε την printf την είχε συμπεριλάβει μέσα στο εκτελέσιμο κώδικα. Όλα αυτά τα προγράμματα θα έπρεπε να γίνουν compiled ξανά για να ``δουν'' την καινούργια printf.


next up previous contents
Next: 2.3 Το πρόγραμμα mean.c Up: 2. Προγραμματισμός στη γλώσσα Previous: 2.1 Γενικά για τη   Contents
Mihalis Kolountzakis 2001-10-21