1η+2η εβδομάδα. 1 Ιστορία της C. 5 Μαρτίου 2012

Σχετικά έγγραφα
1η+2η εβδομάδα. 1 Ιστορία της C. 24 Μαρτίου 2014

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

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

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

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

Εισαγωγή στην γλώσσα προγραμματισμού C

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

3.1 Αριθμητικοί και Λογικοί Τελεστές, Μετατροπές Τύπου (Casting)

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

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

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

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

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

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

Εντολές ελέγχου ροής if, for, while, do-while

Η-Υ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ. Εργαστήριο 2 Εντολές Εισόδου/Εξόδου Τελεστές. Δρ. Γιώργος Λαμπρινίδης 23/10/2015 Η - Υ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ 1

Στοιχειώδης προγραμματισμός σε C++

Μεταβλητές τύπου χαρακτήρα

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

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

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

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

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

Pascal, απλοί τύποι, τελεστές και εκφράσεις

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

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

Η-Υ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ. Εργαστήριο 1 Εισαγωγή στη C. Σοφία Μπαλτζή s.mpaltzi@di.uoa.gr

2ο σετ σημειώσεων. 1 Εντολές εκτέλεσης υπό συνθήκη. 19 Μαρτίου 2012

Τύποι Δεδομένων Είσοδος/Έξοδος

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

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

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

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

ΑΣΚΗΣΗ 2: ΔΟΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ C, ΧΕΙΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ ΚΑΙ ΣΥΝΑΡΤΗΣΕΙΣ ΕΙΣΟΔΟΥ ΚΑΙ ΕΞΟΔΟΥ

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

ΦΥΛΛΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ 1

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

C: Από τη Θεωρία στην Εφαρµογή 2 ο Κεφάλαιο

Βασικές Αρχές Προγραμματισμού

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

Κεφάλαιο ΙV: Δείκτες και πίνακες. 4.1 Δείκτες.

ΚΕΦΑΛΑΙΟ 8 Η ΓΛΩΣΣΑ PASCAL

a = 10; a = k; int a,b,c; a = b = c = 10;

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

Οικονόμου Βαγγέλησ Διάλεξη Νο 2. Δομημένοσ Προγραμματιςμόσ - Διάλεξη 2

Διαδικασία Ανάπτυξης Λογισμικού

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

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

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

Προβλήματα, αλγόριθμοι, ψευδοκώδικας

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 2 η : Βασικές Έννοιες της γλώσσας προγραµµατισµού C Χειµερινό Εξάµηνο 2011

ΑΣΚΗΣΗ 2: ΧΕΙΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ ΣΤΗ C

ΕΡΓΑΣΤΗΡΙΟ 2 ΕΙΣΑΓΩΓΗ ΣΤΗ C. Εργαστήριο 2. Τµήµα Πληροφορικής και Τηλεπικοινωνιών

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

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

Μεταφερσιμότητα Τα προγράμματα μεταφέρονται εύκολα σε διαφορετικά λειτουργικά συστήματα

Ψευδοκώδικας. November 7, 2011

ΓΛΩΣΣΑ ΑΛΦΑΒΗΤΟ ΤΥΠΟΙ ΔΕΔΟΜΕΝΩΝ ΣΤΑΘΕΡΕΣ ΜΕΤΑΒΛΗΤΕΣ

Τμήμα Πληροφορικής & Επικοινωνιών Δρ. Θεόδωρος Γ. Λάντζος

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

ΠΑΝΕΠΙΣΤΗΜΙΟ AΙΓΑIΟΥ & ΑΕΙ ΠΕΙΡΑΙΑ Τ.Τ. Τμήματα Ναυτιλίας και Επιχειρηματικών Υπηρεσιών & Μηχ. Αυτοματισμού ΤΕ. Εισαγωγή στη Python

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

Η δήλωση πού δηµιουργεί αποθήκευση τών δεδοµένων ονοµαζεται ορισµός τής µεταβλητής.

Πίνακες: μια σύντομη εισαγωγή. Πίνακες χαρακτήρων: τα "Αλφαριθμητικά"

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

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

Προγραμματισμός Η/Υ. Ενότητα 2β: Εισαγωγή στη C (Μέρος Δεύτερο)

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

TMHMA TEXNΟΛΟΓΙΑΣ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΤΗΛ/ΝΙΩΝ Προγραμματισμός Ι ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ , Α ΕΞΑΜΗΝΟ Βασίλης Μποζαντζής. Βασίλης Μποζαντζής

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

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

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

Απλά Προγράμματα. Βήματα: 1. Καθορισμός παράστασης δεδομένων στη μνήμη 2. Αλγόριθμος βήματα που περιγράφουν την επεξεργασία των δεδομένων

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

Εισαγωγή στην Πληροφορική & τον Προγραμματισμό

ΒΑΣΙΚΟΙ ΤΥΠΟΙ ΚΑΙ ΠΙΝΑΚΕΣ

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

Εισαγωγή στη JAVA. Εισαγωγή στη Java. Η Java είναι δημιούργημα της SUN MICROSYSTEMS.

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

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

Master Mind εφαρμογή στη γλώσσα προγραμματισμού C

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

Αναπαράσταση Δεδομένων. ΜΥΥ-106 Εισαγωγή στους Η/Υ και στην Πληροφορική

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

Λογικός τύπος Τελεστές σύγκρισης Λογικοί τελεστές Εντολές επιλογής Εμβέλεια Μαθηματικές συναρτήσεις Μιγαδικός τύπος ΔΕΥΤΕΡΗ ΔΙΑΛΕΞΗ

Τμήμα Χρηματοοικονομικής & Ελεγκτικής ΤΕΙ Ηπείρου Παράρτημα Πρέβεζας. Πληροφορική Ι. Αναπαράσταση αριθμών στο δυαδικό σύστημα. Δρ.

ΗΥ-150. Προγραμματισμός

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

Υπερφόρτωση τελεστών

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Pascal. 15 Νοεμβρίου 2011

Οι εντολές ελέγχου της ροής ενός προγράμματος.

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

2.1. Εντολές Σχόλια Τύποι Δεδομένων

Βασικοί τύποι δεδομένων (Pascal) ΕΠΑ.Λ Αλίμου Γ Πληροφορική Δομημένος Προγραμματισμός (Ε) Σχολ. Ετος Κων/νος Φλώρος

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

ΗΥ-150. Προγραμματισμός

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

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

Transcript:

1η+2η εβδομάδα 5 Μαρτίου 2012 1 Ιστορία της C Η γλώσσα C επινοήθηκε στα εργαστήρια Bell της AT&T την περίοδο από το 1969 έως το 1973 κατά κύριο λόγο από τον Dennis Ritchie. Εκείνη τη χρονική περίοδο υπήρχαν ήδη γλώσσες προγραμματισμού με τις οποίες θα μπορούσε κανείς να προγραμματίσει εφαρμογές αλλά δεν υπήρχαν γλώσσες με δυνατότητες χαμηλού επιπέδου με τις οποίες θα μπορούσε κάποιος να προγραμματίσει ένα λειτουργικό σύστημα ή ένα μεταγλωττιστή. Έτσι οι προγραμματιστές λειτουργικών συστημάτων έπρεπε να χρησιμοποιούν κώδικα μηχανής για να προγραμματίσουν λειτουργικά συστήματα. Την ίδια περίοδο, ένας συνάδελφος του Dennis Ritchie, ο Ken Thompson χρησιμοποιούσε τη γλώσσα B για αυτό το σκοπό. Όταν στα Bell Labs παρέλαβαν έναν νέο υπολογιστή τον PDP-11 είδαν ότι η γλώσσα B δεν είχε τις δυνατότητες που έπρεπε να έχει για να φτιαχτεί με αυτήν ένα λειτουργικό σύστημα για το νέο υπολογιστή. Έτσι ο Ritchie ασχολήθηκε με την ανάπτυξη της διαδόχου της B, η οποία ονομάστηκε C. To 1978 o Ritchie με τον Brian Kernighan έγραψαν ένα βιβλίο στο οποίο περιγράφουν τη νέα γλώσσα. Το βιβλίο θεωρείται κλασσικό και αποτέλεσε το ανεπίσημο πρότυπο της γλώσσας. Το συντακτικό της C όπως περιγράφεται εκεί αναφέρεται ως K&R. Κάποια χρόνια μετά, όταν η γλώσσα έγινε πολύ δημοφιλής και έπρεπε να προτυποποιηθεί το Αμερικανικό Εθνικό Ινστιτούτο Προτύπων (ANSI) εξέδωσε το 1989 ένα πρώτο πρότυπο της C το οποίο αναφέρεται και ως C89 ή ANSI C. Ένα χρόνο μετά ο Διεθνής Οργανισμός Προτυποποίησης (ISO) εξέδωσε το ίδιο στην ουσία πρότυπο το οποίο αναφέρεται ως C90 αλλά στην ουσία είναι ίδιο με το C89. Το 1999 εκδόθηκε ένα ακόμα πρότυπο της γλώσσας το οποίο αναφέρεται ως C99 και με αυτήν την έκδοση της γλώσσας θα ασχοληθούμε στο μάθημα¹. Περισσότερες πληροφορίες (ιστορικές και μη) για τη C μπορεί κανείς να βρει στη wikipedia. Το βιβλίο των Kernighan-Ritchie θεωρείται κλασσικό και αξίζει κανείς να το διαβάσει παρόλο που είναι μάλλον ακατάλληλο για διδασκαλία σε αρχάριους. Μπορείτε να βρείτε στο δίκτυο διάφορες πηγές όπως το βιβλίο The C Book ή tutorials και βοηθήματα όπως αυτά εδώ, εδώ και εδώ. Σημειώσεις, εργασίες και όποιο άλλο υλικό του μαθήματος σας δίνεται από τον διδάσκοντα θα αναρτάται εδώ. ¹Στα τέλη του 2011 εκδόθηκε το C11 το οποίο είναι πολύ φρέσκο. Η συμβατότητα των μεταγλωττιστών με αυτό θα είναι μικρή για αρκετό καιρό ακόμα οπότε δε θα ασχοληθούμε ιδιαίτερα με αυτό. 1

2 Ένα απλό πρόγραμμα σε C Το πρόγραμμα 1 τυπώνει στην οθόνη το μήνυμα Hello, world!. 1 # include <stdio.h> Listing 1: Πρόγραμμα Hello 2 3 int main() 4 { 5 printf("hello, world!"); 6 7 return 0; 8 } Η γραμμή 1 δεν είναι κάποια εντολή της C αλλά μία εντολή του προεπεξεργαστή της C, δηλαδή ενός προγράμματος που τρέχει πριν από το μεταγλωττιστή και πραγματοποιεί κάποιες μετατροπές στο πρόγραμμα πριν γίνει η μεταγλώττιση. Η συγκεκριμένη εντολή λέει στον προεπεξεργαστή να βρει το αρχείο stdio.h και να βάλει τα περιεχόμενά του στη γραμμή 1 του παραπάνω προγράμματος. Τα αρχεία με κατάληξη.h συνήθως δεν περιέχουν εντολές της C αλλά δηλώσεις συναρτήσεων που βρίσκονται μεταγλωττισμένες ήδη και πακεταρισμένες σε βιβλιοθήκες του συστήματος προκειμένου να διευκολύνουν τον προγραμματιστή. Τα αρχεία αυτά ονομάζονται αρχεία συμπερίληψης (include files) και παρέχονται από τον προμηθευτή του μεταγλωττιστή. Το συγκεκριμένο αρχείο stdio.h περιέχει δηλώσεις συναρτήσεων της βιβλιοθήκης εισόδου/εξόδου και το όνομά του προκύπτει ως συντόμευση των λέξεων standard input/output. Η συνάρτηση printf της γραμμής 5 είναι μία από αυτές τις συναρτήσεις της στάνταρ βιβλιοθήκης και υλοποιεί την εμφάνιση μηνυμάτων και τιμών στην οθόνη. Το όνομα της προκύπτει από τις λέξεις print function (συνάρτηση εκτύπωσης). Για να καλέσουμε μια συνάρτηση στη C γράφουμε το όνομά της ακολουθούμενο από τα πραγματικά της ορίσματα. Στη συγκεκριμένη περίπτωση το μοναδικό όρισμα της printf είναι μία συμβολοσειρά (string) που περιέχει το μήνυμα που θέλουμε να τυπωθεί στην οθόνη. Στην C οι συμβολοσειρές περικλείονται μέσα σε διπλά εισαγωγικά. Οτιδήποτε βρίσκεται μέσα στα διπλά εισαγωγικά τυπώνεται στην οθόνη ως έχει χωρίς η γλώσσα να το υποβάλει σε κάποια ιδιαίτερη επεξεργασία². Παρατηρήστε επίσης ότι η εντολή της γραμμής 5 τερματίζεται με το ελληνικό ερωτηματικό. Κάθε εντολής της C τερματίζεται με το ελληνικό ερωτηματικό, όπως και η εντολή return 0 της γραμμής 7. Η γραμμή 3 είναι η επικεφαλίδα (header) μίας συνάρτησης (function) με όνομα main. Θα δούμε αναλυτικά τον τρόπο ορισμού συναρτήσεων στην C αργότερα. Προς το παρόν αρκεί να πούμε ότι κάθε εκτελέσιμη εντολή σε ένα πρόγραμμα C πρέπει να βρίσκεται μέσα σε μία συνάρτηση. Μπορούμε να δώσουμε οποιοδήποτε όνομα στις συναρτήσεις που ορίζουμε (αρκεί να ακολουθούν τους κανόνες της γραμματικής της C) αλλά κάθε πρόγραμμα πρέπει να περιέχει μία συνάρτηση η οποία ονομάζεται main. Η εκτέλεση ενός προγράμματος C συνίσταται στην εκτέλεση αυτής της συνάρτησης, ή με άλλα λόγια η εκτέλεση ενός προγράμματος C ξεκινάει με την πρώτη εντολή της συνάρτησης main και συνεχίζεται με τις επόμενες μέχρι την τελευταία της εντολή. Στο συγκεκριμένο μας πρόγραμμα ο ορισμός της main δηλαδή η επικεφαλίδα της μαζί με τις εντολές που εκτελούνται όταν καλείται ²Με εξαίρεση τους χαρακτήρες % και \ για τους οποίους θα μιλήσουμε στη συνέχεια 2

βρίσκονται στις γραμμές 3 έως 8. Οι γραμμές 4 έως 8 είναι το σώμα (body) της συνάρτησης και πρέπει να περικλείονται μέσα σε ένα ζευγάρι άγκιστρων {}. Στη γραμμή 3 επίσης βλέπουμε ένα ζευγάρι παρενθέσεων αμέσως μετά το όνομα της συνάρτησης. Εκεί μπορούμε να δηλώσουμε τις τυπικές παραμέτρους της συνάρτησης. Στο παράδειγμά μας ορίζουμε τη main χωρίς παραμέτρους αλλά θα δούμε στη συνέχεια ότι έχουμε άλλη μία επιλογή. Επίσης βλέπουμε τη λέξη int πριν από το όνομα της συνάρτησης. Αυτό σημαίνει ότι η συνάρτηση επιστρέφει έναν ακέραιο. Στη C όλες οι συναρτήσεις πρέπει να δηλώνουν τι επιστρέφουν, ακόμα και όταν δεν επιστρέφουν κάποια τιμή. Οι συναρτήσεις μπορούν να επιστρέφουν τιμές στις καλούσες με την εντολή return. Στη γραμμή 7 βλέπουμε ότι στο πρόγραμμά μας η main επιστρέφει την τιμή 0. 3 Βασικοί τύποι και δηλώσεις μεταβλητών Στη C έχουμε τέσσερις βασικούς τύπους: int Για ακεραίους, float για αριθμούς κινητής υποδιαστολής, double για αριθμούς κινητής υποδιαστολής διπλής ακρίβειας και char για χαρακτήρες³. Το εύρος κάθε τύπου, δηλαδή το σύνολο τιμών των μεταβλητών αυτού του τύπου καθορίζεται μόνο εν μέρει από το πρότυπο της C. Το πρότυπο δίνει την ελευθερία σε αυτόν που αναπτύσσει το μεταγλωττιστή να ορίσει το εύρος τιμών για κάθε έναν από τους παραπάνω τύπους και για κάθε συγκεκριμένη αρχιτεκτονική υπολογιστή αρκεί να κινείται μέσα σε κάποια όρια. Για παράδειγμα το πρότυπο ορίζει ότι ένας ακέραιος θα πρέπει να παριστάνει αριθμούς τουλάχιστον στο εύρος από -32768 μέχρι και 32767. Αυτό δεν σημαίνει ότι σε κάθε μεταγλωττιστή θα ισχύει κάτι τέτοιο καθώς κάποιοι μεταγλωττιστές μπορεί να ορίζουν τον ακέραιο τύπο να παριστάνει μεγαλύτερο εύρος τιμών. Στην περίπτωση που ο προγραμματιστής δεν καλύπτεται από το εύρος τιμών των ακεραίων σε κάποιο συγκεκριμένο μεταγλωττιστή δίνονται κάποιες δυνατότητες περαιτέρω προσδιορισμού ενός τύπου με τους προσδιοριστές (specifiers) long και short. Συγκεκριμένα ο τύπος long int δηλώνει έναν ακέραιο μεγαλύτερου ή ίσου εύρους από εκείνο του int και ο short int δηλώνει έναν ακέραιο με εύρος μικρότερο ή ίσο από εκείνο του int. Επιπρόσθετα, δίνεται η δυνατότητα χρησιμοποίησης του προσδιοριστή long δύο φορές δηλαδή ορίζεται και ο τύπος long long int προκειμένου να δηλωθεί ένας ακέραιος με εύρος μεγαλύτερο ή ίσο από εκείνο του long int. Ο προσδιοριστής short δεν μπορεί να χρησιμοποιηθεί δύο φορές. Επίσης, όταν χρησιμοποιείται κάποιος από τους δύο παραπάνω προσδιοριστές short ή long η λέξη int μπορεί να παραληφθεί. Δηλαδή ο τύπος long long int μπορεί να γραφεί και ως long long όπως και ο τύπος short int μπορεί να γραφτεί και ως short. ³Το πρότυπο C99 ορίζει και δύο ακόμα τύπους τους _Bool και _Complex με τους οποίους δε θα ασχοληθούμε καθώς δεν αναφέρονται πουθενά στην πιστοποίηση 3

Οι προσδιοριστές short και long μπορούν να χρησιμοποιηθούν μόνο σε τύπους int με μία και μόνη εξαίρεση: ο long μπορεί να χρησιμοποιηθεί και με τον τύπο double. Επίσης, ένα άλλο είδος προσδιοριστών μπορεί να καθορίσει στην περίπτωση βαθμωτών τύπων (int και char) αν θέλουμε ο τύπος να θεωρείται προσημασμένος ή όχι. Οι προσδιοριστές αυτοί είναι οι signed και unsigned οι οποίοι μπαίνουν πριν από το όνομα του βασικού τύπου (και πριν από τους προσδιοριστές long ή short αν αυτοί υπάρχουν). Έτσι, επιπρόσθετα στους παραπάνω συνδυασμούς τύπων και προσδιοριστών μπορούμε να δηλώσουμε μία μεταβλητή ως τύπου signed int ή unsigned short int ή signed char. Ξανατονίζουμε ότι οι προσδιοριστές αυτοί δεν μπορούν να χρησιμοποιηθούν με τύπους κινητής υποδιαστολής δηλαδή float και double. Ο λόγος ύπαρξης αυτών των προσδιοριστών είναι το γεγονός ότι η αναπαράσταση του προσήμου σε ένα βαθμωτό τύπο απαιτεί τη δέσμευση ενός bit. Καταργώντας τη χρησιμοποίηση του bit αυτού για την αναπαράσταση του προσήμου μπορούμε να αναπαραστήσουμε αριθμούς διπλάσιου εύρους. Ένα τελευταίο σημείο είναι ότι σε περίπτωση που ο προσδιοριστής προσήμου δεν αναφέρεται, τότε ο τύπος θεωρείται προσημασμένος. Δηλαδή ο τύπος long int θεωρείται ισοδύναμος με τον προσημασμένο signed long int. Για να δηλώσουμε μια μεταβλητή πρέπει να αναφέρουμε το όνομα του τύπου της ακολουθούμενο από το όνομά της και φυσικά το ελληνικό ερωτηματικό, π.χ. κάπως έτσι: int a; ή long double b;. Για παράδειγμα στο listing 2 δηλώνεται μία μεταβλητή a στην οποία ανατίθεται η τιμή 2 και στη συνέχεια η τιμή της a τυπώνεται στην οθόνη. 1 # include <stdio.h> Listing 2: Δήλωση μεταβλητής 2 3 int main() 4 { 5 int a; 6 7 a = 2; 8 printf("%d\n", a); 9 10 return 0; 11 } Η δήλωση της μεταβλητής γίνεται στη γραμμή 5. Στη γραμμή 7 γίνεται η ανάθεση της τιμής 2 στη μεταβλητή και στην επόμενη γραμμή τυπώνεται στην οθόνη. Στη συνέχεια θα πούμε περισσότερες λεπτομέρειες για τα ιερογλυφικά που εμφανίζονται στη γραμμή 8 μέσα στα διπλά εισαγωγικά. Προς το παρόν θα πρέπει απλώς να μάθετε τη γραμμή 8 απ έξω και να βάζετε αντί για το όνομα της μεταβλητής a το όνομα της μεταβλητής που θέλετε να εμφανιστεί στην οθόνη. Επίσης, αντί για %d που χρησιμοποιείται για την εκτύπωση ακεραίων θα πρέπει να χρησιμοποιείτε %f για την εκτύπωση αριθμών κινητής υποδιαστολής. Ενα τελευταιο σημείο σχετικά με το σημείο στο οποίο επιτρέπεται να δηλώνονται μεταβλητές. Το παλιότερο πρότυπο της γλώσσας (C89, C90) ορίζει ότι όλες οι δηλώσεις τοπικών⁴ μεταβλητών πρέπει να βρίσκονται αμέσως μετά το άγκιστρο που ξεκινάει το σώμα μίας συνάρτησης και πριν από ⁴Υπάρχουν και οι καθολικές (global) μεταβλητές οι οποίες δηλώνονται έξω από το σώμα οποιασδήποτε συνάρτησης. 4

οποιαδήποτε εκτελέσιμη εντολή. Στο παραπάνω παράδειγμα δε θα μπορούσαμε να δηλώσουμε μία μεταβλητή π.χ. στη γραμμή 9 γιατί αυτή βρίσκεται μετά την εκτελέσιμη εντολή της γραμμής 8. Με άλλα λόγια πρέπει όλες οι δηλώσεις μεταβλητών να βρίσκονται μαζεμένες αμέσως μετά το άγκιστρο της γραμμής 4 για την περίπτωση της main. Παρόλα αυτά, είναι σύνηθες ο μεταγλωττιστής να μην γκρινιάζει αν βάλετε μία δήλωση σε κάποιο ξεκάρφωτο σημείο. Αυτό μπορεί να οφείλεται αφενός στο ότι το νεότερο πρότυπο C99 επιτρέπει τις δηλώσεις να ανακατεύονται με τον κώδικα ή αφετέρου στο ότι η C++ ανέκαθεν επέτρεπε κάτι τέτοιο οπότε πολλοί μεταγλωττιστές το επέτρεπαν σαν ευκολία. Εσείς καλύτερα να κάνετε αυτό που λένε οι κανόνες και που κατά πάσα πιθανότητα θα ισχύει σε κάθε μεταγλωττιστή της C και το οποίο θα αντιλαμβάνεται οποιοσδήποτε διορθωτής στην πιστοποίηση: Βάλτε όλες τις δηλώσεις μεταβλητών μαζεμένες αμέσως μετά το άγκιστρο της συνάρτησης μέσα στην οποία δηλώνονται και πριν από οποιαδήποτε εκτελέσιμη εντολή. Ένα τελευταίο ερώτημα που μπορεί να απασχολεί τους περίεργους είναι το εξής: Ποια είναι τα πραγματικά εύρη τιμών για τους παραπάνω τύπους; Το πρότυπο ορίζει ότι τα εύρη τιμών για κάθε τύπο πρέπει να ορίζονται ρητά στο αρχείο limits.h. Για παράδειγμα το listing 3 δείχνει πώς μπορούμε να δούμε το μεγαλύτερο μη προσημασμένο long long int στο σύστημά μας, καθώς και την ελάχιστη και μέγιστη τιμή ενός προσημασμένου long long int. 1 # include <stdio.h> 2 # include <limits.h> Listing 3: Όρια long long int 3 4 int main() 5 { 6 printf(" Maximum unsigned long long int: % llu\n", ULLONG_MAX); 7 printf(" Minimum long long int: % lld\n", LLONG_MIN); 8 printf(" Maximum long long int: % lld\n", LLONG_MAX); 9 10 return 0; 11 } Οι σταθερές ULLONG_MAX ορίζονται στο αρχείο limits.h στο οποίο μπορείτε να ανατρέξετε αν θέλετε. Επίσης, οι παραπάνω σταθερές ορίζονται και περιγράφονται στην ενότητα 5.2.4.2 του προτύπου. Αντίστοιχα όρια ορίζονται στο αρχείο float.h. 4 Εισαγωγικά για τη φορμαρισμένη είσοδο και έξοδο Θα ασχοληθούμε με τη φορμαρισμένη είσοδο και έξοδο αναλυτικά σε επόμενη ενότητα αλλά είναι χρήσιμο σε πρώτη φάση να δούμε πώς μπορούμε στη C να τυπώνουμε μεταβλητές και σταθερές στην οθόνη όπως και να τις διαβάζουμε από το πληκτρολόγιο. Το απλό παράδειγμα 4 δηλώνει μία ακέραια μεταβλητή a και την τυπώνει με τη συνάρτηση printf. 1 # include <stdio.h> Listing 4: printf 2 3 int main() 5

4 { 5 int a; 6 7 a = 2; 8 printf("h timn tns a eivai: %d\n", a); 9 10 a = -1; 11 printf("h timn tns a eivai: %d\n", a); 12 13 return 0; 14 } Αν μεταγλωττίσετε το παραπάνω πρόγραμμα και το τρέξετε θα δείτε στην οθόνη τα παρακάτω: H timn tns a eivai: 2 H timn tns a eivai: -1 Ας δούμε αναλυτικά πώς δουλεύει η printf. Δυστυχώς δεν υπάρχει δυνατότητα να γράψουμε μία εντολή της μορφής printf(a); όπως θα κάναμε σε άλλες γλώσσες για να τυπώσουμε την τιμή της a στην οθόνη⁵. Το πρώτο όρισμα της printf πρέπει πάντα να είναι μία συμβολοσειρά δηλάδη ένα σύνολο χαρακτήρων κλεισμένων μέσα σε διπλά εισαγωγικά. Όπως είδαμε και στο πρόγραμμα Hello, world! η C θα τυπώσει στην οθόνη έναν προς έναν τους χαρακτήρες της συμβολοσειράς. Η εντολή printf("hello, world!"); θα τυπώσει στην οθόνη ακριβώς το μήνυμα Hello, world! Στο πρόγραμμα 4 όμως βλέπουμε ότι η συμβολοσειρά H timn tns a eivai: %d\n δεν τυπώνεται ακριβώς έτσι. Για την ακρίβεια δεν βλέπουμε ούτε το %d ούτε το \n. Το πρώτο είναι ένας προσδιοριστής (specifier) και το δεύτερο ένας χαρακτήρας διαφυγής (escape character). Ο κανόνας είναι ότι η printf εκτός από το πρώτο όρισμα που είναι μία συμβολοσειρά και είναι υποχρεωτικό, μπορεί να δεχτεί και οσαδήποτε ακόμα ορίσματα χωρισμένα με κόμματα το ένα από το άλλο των οποίων θα τυπώσει τις τιμές. Αυτό όμως από μόνο του δεν αρκεί. Η printf θέλει να δηλώσουμε ρητά τον τρόπο με τον οποίο θέλουμε να τυπωθεί η κάθε παράσταση. Για παράδειγμα μπορεί να μη θέλουμε απλώς να τυπώσουμε μία τιμή αλλά να τη στοιχίσουμε μαζί με άλλες οπότε θα πρέπει να δηλώσουμε πόσες θέσεις θα καταλαμβάνει. Ή μπορεί να θέλουμε να τυπωθεί στοιχισμένη δεξιά ή αριστερά, να θέλουμε ο κενός χώρος όταν γίνεται στοίχιση να γεμίζει με κενά ή με μηδενικά. Στην περίπτωση των αριθμών κινητής υποδιαστολής μπορεί να έχουμε όλα τα προηγούμενα αλλά επίσης να θέλουμε να γίνεται εκτύπωση με συγκεκριμένο αριθμό δεκαδικών ψηφίων όπως επίσης μπορεί να θέλουμε εκτύπωση σε απλή ή επιστημονική γραφή. Οπότε για κάθε παράσταση που ακολουθεί την αρχική συμβολοσειρά και θέλουμε να τυπωθεί, πρέπει να συμπεριλάβουμε τον αντίστοιχο προσδιοριστή μέσα στη συμβολοσειρά. Οι προσδιοριστές ξεκινούν πάντα με το χαρακτήρα %. Πρέπει να υπάρχουν τόσοι προσδιοριστές όσες και παραστάσεις μετά τη συμβολοσειρά δηλαδή τα % μέσα στη συμβολοσειρά πρέπει να είναι τόσα όσες και οι παραστάσεις που την ακολουθούν. Ο κάθε προσδιοριστής αντιστοιχίζεται σε μία παράσταση όπως τους διαβάζουμε από τα αριστερά προς τα ⁵αν και μπορούμε να γράψουμε μία δική μας συνάρτηση για αυτό το σκοπό 6

δεξιά. Δηλαδή στην εντολή printf("mpla %d mplou %u mpli %x", a, b, c); ο προσδιοριστής %d αντιστοιχεί στη μεταβλητή a, ο προσδιοριστής %u στη μεταβλητή b και ο %x στη c. Τελικά, όταν η printf εκτελείται ξεκινά να τυπώνει έναν προς έναν τους χαρακτήρες της συμβολοσειράς που αποτελεί το πρώτο της όρισμα από τα αριστερά προς τα δεξιά. Αν συναντήσει έναν προσδιοριστή, τον επεξεργάζεται και ανάλογα τυπώνει την αντίστοιχη παράσταση (χωρίς να τυπώσει τον προσδιοριστή). Συνεχίζει με τον ίδιο τρόπο μέχρι το τέλος της συμβολοσειράς. Στο τελευταίο παράδειγμα δηλαδή η printf θα τύπωνε τους χαρακτήρες mpla και ένα κενό. Μετά θα συναντούσε τον προσδιοριστή %d οπότε θα τύπωνε την τιμή της μεταβλητής a⁶. Μετά θα τύπωνε ένα κενό και τους χαρακτήρες mplou και ένα κενό. Έπειτα θα έβρισκε τον προσδιοριστή %u οπότε θα τύπωνε την τιμή της αντίστοιχης παράστασης δηλαδή της μεταβλητής b κ.ο.κ. Με ανάλογο τρόπο μπορεί κανείς να χρησιμοποιήσει τη συνάρτηση scanf για να διαβάσει τιμές μεταβλητών από το πληκτρολόγιο. Με την παρακάτω εντολή διαβάζεται μία προσημασμένη ακέραια τιμή από το πληκτρολόγιο και αποθηκεύεται στη μεταβλητή a: scanf("%d", &a);. Προσοχή στο & που βρίσκεται πριν από το όνομα της μεταβλητής. Στην ενότητα 4.1 που ακολουθεί περιγράφονται σχετικά πιο αναλυτικά οι προσδιοριστές χωρίς να περιγράφονται πλήρως. Ακόμα και σε αυτήν την απλουστευμένη παρουσίαση είναι αρκετά πολύπλοκοι. Δεν χρειάζεται να τους διαβάσετε και να τους κατανοήσετε πλήρως σε πρώτη ανάγνωση. Απλώς κρατήστε τους σαν αναφορά. Αυτό που χρειάζεται να ξέρετε σε πρώτη φάση είναι ότι μπορείτε να χρησιμοποιείτε τον προσδιοριστή %d για ακέραιους, τον %u για μη-προσημασμένους ακέραιους και τον %c για χαρακτήρες. 4.1 Προσδιοριστές Η σύνταξη των προσδιοριστών είναι αρκετά πολύπλοκη και περιγράφεται αναλυτικά στην ενότητα 7.9.16.1 του προτύπου C99. Για λόγους πληρότητας και μόνο τους αναφέρουμε εδώ αλλά πρέπει να τονίσουμε ότι δεν είναι απαραίτητο να γνωρίζει κανείς όλα τα παρακάτω για να ξεκινήσει να μαθαίνει την C. Η μορφή ενός προσδιοριστή είναι: Μία ή περισσότερες σημαίες (flags) (προαιρετικά), ένα ελάχιστο μήκος πεδίου (προαιρετικά), η ακρίβεια (προαιρετικά), ένας τροποποιητής μεγέθους (προαιρετικά αλλά χρησιμοποιείται συχνά) και ένας μετατροπέας. Από τα παραπάνω το πιο σημαντικό είναι το τελευταίο δηλαδή ο μετατροπέας. Αυτός καθορίζει ως τι θα χειριστεί η printf την παράσταση που της ζητείται να τυπώσει. Το παρακάτω παράδειγμα (listing 5) βοηθάει να γίνει αυτό πιο κατανοητό: 1 # include <stdio.h> Listing 5: Μυστηριώδης printf ⁶σύμφωνα με τον τρόπο που ορίζει ο προσδιοριστής %d, θα τους δούμε αναλυτικά στη συνέχεια 7

2 3 int main() 4 { 5 int a = -1; 6 7 printf("h timn tns a eivai: %d\n", a); 8 printf("h timn tns a eivai: %u\n", a); 9 10 return 0; 11 } Αν τρέξετε το παραπάνω σε έναν υπολογιστή που αποθηκεύει ακεραίους με τη μορφή συμπληρώματος ως προς 2 θα δείτε στην οθόνη τα εξής: H timn tns a eivai: -1 H timn tns a eivai: 4294967295 Τελικά, ποια είναι η τιμή της μεταβλητής a; Γιατί η πρώτη printf τυπώνει -1 ενώ η δεύτερη 4294967295; Κατά μία έννοια η μεταβλητή a είναι και τα δύο. Από φυσική άποψη, από την άποψη του υπολογιστή στον οποίο έτρεξε το παραπάνω παράδειγμα δηλαδή, η μεταβλητή a είναι 4 συνεχόμενα bytes δηλαδή 32 bits τα οποία έχουν όλα την τιμή 1. Αν αυτά τα 32 bits τα θεωρήσει κανείς ένα προσημασμένο ακέραιο αριθμό τότε στη μορφή συμπληρώματος ως προς 2 αυτός ο αριθμός θα ήταν ο -1. Αν τα θεωρήσει κανείς ένα μη προσημασμένο αριθμό τότε είναι ο αριθμός 2 3 2 1 = 4294967295. Οπότε τελικά ο μετατροπέας που ακολουθεί το % στην printf καθορίζει ως τι πρέπει η συνάρτηση να τυπώσει την παράσταση που ακολουθεί. Ο μετατροπέας d στη γραμμή 7 λέει στην printf να τυπώσει την a ως προσημασμένο ακέραιο (-1) ενώ ο u στη γραμμή 8 ως μη προσημασμένο ακέραιο (4294967295). Οι πιο συνηθισμένοι μετατροπείς είναι: d,i Μετατροπή σε προσημασμένο ακέραιο. u,o,x,x Μετατροπή σε μη-προσημασμένο ακέραιο ο οποίος θα τυπώθεί ως δεκαδικός (u), οκταδικός (o), δεκαεξαδικός με πεζά (x) ή δεκαεξαδικός με κεφαλαία (X). f,f,e,e,g,g,a,a Μετατροπή σε τύπο double ο οποίος θα τυπωθεί ως αριθμός με δεκαδικά ψηφία (f,f), σε επιστημονική αναπαράσταση με βάση και εκθέτη (e,e), σε κάποια από τις δύο προηγούμενες μορφές ανάλογα με κάποια κριτήρια (g,g) ή σε επιστημονική αναπαράσταση με βάση το 2 (a,a). Η διαφορά του πεζού μετατροπέα (f,e,g,a) από τον αντίστοιχο κεφαλαίο (F,E,G,A) είναι στην περίπτωση που πρέπει να εκτυπωθεί και κάποιος χαρακτήρας. Οι μετατροπείς της πρώτης ομάδας τον τυπώνουν πεζό ενώ της δεύτερης κεφαλαίο. c Μετατροπή σε χαρακτήρα. s Μετατροπή σε συμβολοσειρά. p Μετατροπή σε δείκτη. 8

n Δε θέλετε να μάθετε⁷. % Απλώς τυπώνει το %. Το παράδειγμα 6 ίσως είναι διαφωτιστικό: 1 # include <stdio.h> Listing 6: Διάφοροι μετατροπείς 2 3 int main() 4 { 5 int a = 74; 6 7 printf(" Metatropeas d: %d\n", a); 8 printf(" Metatropeas i: %i\n", a); 9 printf(" Metatropeas u: %u\n", a); 10 printf(" Metatropeas o: %o\n", a); 11 printf(" Metatropeas x: %x\n", a); 12 printf(" Metatropeas X: %X\n", a); 13 printf(" Metatropeas c: %c\n", a); 14 printf(" Metatropeas p: %p\n", a); 15 16 return 0; 17 } Αν το τρέξετε θα δείτε στην οθόνη το παρακάτω: Metatropeas d: 74 Metatropeas i: 74 Metatropeas u: 74 Metatropeas o: 112 Metatropeas x: 4a Metatropeas X: 4A Metatropeas c: J Metatropeas p: 0x4a Οι προσδιοριστές d και i είναι το ίδιο πράγμα. Επειδή ο αριθμός 74 είναι θετικός ακέραιος δεν αλλάζει κάτι αν τον θεωρήσει κανείς μη-προσημασμένο (τρίτη γραμμή, μετατροπέας u). Η τέταρτη γραμμή είναι ο αριθμός 74 σε οκταδικό σύστημα (1 64 + 1 8 + 2 = 74). Στην πέμπτη και έκτη γραμμή είναι η δεκαεξαδική αναπαράσταση του αριθμού (4 16 + 10 = 74) με πεζό και κεφαλαίο το a αντίστοιχα. Στην επόμενη βλέπουμε ότι ο χαρακτήρας με κωδικό ASCII 74 είναι ο J. Και στο τέλος βλέπουμε τη δεκαεξαδική αναπαράσταση του 74 με το πρόθεμα 0x. Προαιρετικά στους προσδιοριστές μπορούμε να χρησιμοποιήσουμε πριν από το μετατροπέα έναν τροποποιητή μεγέθους. Αυτοί είναι⁸: ⁷Αφού επιμένετε: Η παράσταση θεωρείται δείκτης σε έναν μη-προσημασμένο ακέραιο. Σε αυτόν η printf γράφει πόσους χαρακτήρες έχει τυπώσει μέχρι εκείνη τη στιγμή. ⁸Υπάρχουν και οι j, z, t στους οποίους δε θα αναφερθούμε. 9

hh Σημαίνει ότι ο επόμενος μετατροπέας αναφέρεται σε έναν χαρακτήρα. h Ο επόμενος μετατροπέας αναφέρεται σε έναν short. l Ο επόμενος μετατροπέας αναφέρεται σε έναν long int. ll Ο επόμενος μετατροπέας αναφέρεται σε έναν long long int. L Ο επόμενος μετατροπέας αναφέρεται σε έναν long double. 5 Τελεστές Η C παρέχει μία πληθώρα τελεστών. Σε γενικές γραμμές μπορούμε να τους διακρίνουμε σε αριθμητικούς, συσχετιστικούς, λογικούς, bit-τελεστές και κάποιους ειδικούς τελεστές που δεν μπορούν να ενταχτούν σε κάποια από τις παραπάνω καθώς εκτελούν ιδιαίτερες λειτουργίες. 5.1 Αριθμητικοί τελεστές Οι αριθμητικοί τελεστές πραγματοποιούν αριθμητικές πράξεις στα ορίσματά τους. Μπορούμε και αυτούς περαιτέρω να τους διακρίνουμε σε κατηγορίες. Υπάρχουν για παράδειγμα δυαδικοί τελεστές δηλαδή τελεστές που επιδρούν σε δύο ορίσματα και δίνουν ένα αποτέλεσμα σε αντιδιαστολή με τους μοναδικούς τελεστές οι οποίοι δέχονται ένα και μόνο όρισμα. Οι τελεστές αυτοαύξησης και αυτομείωσης (οι οποίοι είναι μοναδικοί) μπορούν να χρησιμοποιηθούν είτε ως προθεματικοί (πριν το όρισμά τους) είτε ως μεταθεματικοί (μετά το όρισμά τους). Πίνακας 1: Αριθμητικοί τελεστές Τελεστής Πράξη Τύπος + Πρόσθεση Δυαδικός⁹ - Αφαίρεση Δυαδικός * Πολλαπλασιασμός Δυαδικός / Διαίρεση Δυαδικός % Ακέραιο υπόλοιπο Δυαδικός ++ Μοναδιαία αύξηση Μοναδικός -- Μοναδιαία μείωση Μοναδικός Στον πίνακα 5.1 αναγράφονται οι δυαδικοί αριθμητικοί τελεστές της γλώσσας και η λειτουργία τους. Οι τελεστές πρόσθεσης, αφαίρεσης, διαίρεσης και πολλαπλασιασμού έχουν τις προφανείς σημασίες. Ένα σημείο που είναι καλό να το έχει κανείς υπόψη του είναι ότι όταν τα ορίσματα είναι διαφορετικών τύπων τότε σιωπηρά η γλώσσα πραγματοποιεί κάποιες μετατροπές ώστε να μην υπάρχει απώλεια στην ακρίβεια του αποτελέσματος. Δηλαδή η τιμή του μικρότερου τύπου μετατρέπεται στον μεγαλύτερο. Για παράδειγμα αν πρόκειται να πραγματοποιηθεί η πράξη a + b και ο a είναι float ενώ ο b είναι long double, τότε η τιμή του a μετατρέπεται σε κάποιο προσωρινό χώρο αποθήκευσης 10

σε long double και μετά προστίθεται με την τιμή του b. Τονίζουμε ότι η μεταβλητή a δεν αλλάζει αλλά η τιμή της αποθήκευεται σε έναν άλλο χώρο με διαφορετική μορφή. Μία ακόμα παρατήρηση για τους παραπάνω προφανείς τελεστές είναι ότι ο τελεστής διαίρεσης αποκόπτει τα δεκαδικά ψηφία του αποτελέσματος όταν τα ορίσματά του είναι ακέραιοι, δηλαδή πραγματοποιεί ακέραια διαίρεση. Επίσης ο τελεστής ακέραιου υπολοίπου πραγματοποιείται μόνο σε ακεραίους. Σε περίπτωση που δοθούν ορίσματα κινητής υποδιαστολής τότε αποκόπτεται το δεκαδικό τους μέρος. Τέλος, οι τελεστές μοναδιαίας αύξησης και μείωσης δέχονται ένα μόνο όρισμα το οποίο αυξάνουν ή μειώνουν κατά μία μονάδα αντίστοιχα. Μπορούν να χρησιμοποιηθούν ως προθεματικοί τελεστές, δηλαδή πριν το όρισμά τους έτσι: ++a ή --a αλλά και ως μεταθεματικοί τελεστές, δηλαδή μετά το όρισμά τους, έτσι: a++ ή a--. Και στις δύο περιπτώσεις το αποτέλεσμα θα είναι το όρισμα να αυξηθεί ή να μειωθεί κατά μία μονάδα. Η διαφορά είναι ότι στην περίπτωση του προθεματικού τελεστή η αύξηση θα γίνει πριν η γλώσσα υπολογίσει την τιμή της έκφρασης ++a ενώ στην περίπτωση του μεταθεματικού τελεστή θα υπολογιστεί μετά. Δείτε το πρόγραμμα 7. 1 # include <stdio.h> 2 3 int main() 4 { 5 int a; 6 7 a = 2; Listing 7: Μοναδιαία αύξηση προ- και μεταθεματικά 8 printf("h a me metathematiko telesti ayxisis: %d\n", a++); 9 printf(" Telika i a eivai: %d\n", a); 10 11 a = 2; 12 printf("h a me prothematiko telesti ayxisis: %d\n", ++a); 13 printf(" Telika i a eivai: %d\n", a); 14 15 return 0; 16 } Οι γραμμές 7 έως 9 και 11 έως 13 κάνουν περίπου το ίδιο πράγμα: Θέτουν την τιμή 2 στη μεταβλητή a, μετά τυπώνουν την τιμή της έκφρασης a++ ή της ++a στις γραμμές 8 και 12 αντίστοιχα και τέλος τυπώνουν την τιμή της μεταβλητής a στις γραμμές 9 και 13. Αν τρέξετε το πρόγραμμα θα δείτε ότι τόσο στη γραμμή 9 όσο και στη γραμμή 13 η τελική τιμή της μεταβλητής a είναι 3. Δηλαδή, τελικά η τιμή της a αυξάνεται κατά μία μονάδα είτε χρησιμοποιηθεί ο προθεματικός είτε ο μεταθεματικός τελεστής. Η διαφορά είναι ότι η γραμμή 8 τυπώνει στην οθόνη 2 ενώ η γραμμή 12 τυπώνει 3. Ο λόγος είναι ότι στη γραμμή 8 πρώτα υπολογίζεται η τιμή της μεταβλητής a και δίνεται για επεξεργασία στην printf και μετά (αφότου τυπωθεί) αυξάνεται η τιμή της κατά 1. Ενώ στη γραμμή 12, πρώτα αυξάνεται η τιμή της μεταβλητής a κατά 1 και μετά αυτό που προκύπτει δίνεται στην printf για επεξεργασία. 11

5.2 Bit τελεστές Μια σειρά τελεστών στη C εκτελεί πράξεις στα επιμέρους bit των ορισμάτων τους. Οι τελεστές αυτοί εφαρμόζονται μόνο σε ορίσματα ακέραιου τύπου. Στον πίνακα 5.2 φαίνονται οι τελεστές αυτοί και Πίνακας 2: Bit τελεστές Τελεστής Πράξη & Λογικό ΚΑΙ Λογικό Ή ^ Λογικό ΑΠΟΚΛΕΙΣΤΙΚΟ Η ~ Συμπλήρωμα ως προς ένα << Αριστερή ολίσθηση >> Δεξιά ολίσθηση η πράξη που ο καθένας πραγματοποιεί. Όλοι είναι δυαδικοί τελεστές εκτός από τον ~ ο οποίος είναι προθεματικός μοναδικός τελεστής. Οι τελεστές &, και ^ εφαρμόζουν αντίστοιχα τις λογικές πράξεις ΚΑΙ, Η και ΑΠΟΚΛΕΙΣΤΙΚΟ Ή αντίστοιχα στα αντίστοιχα bit των ορισμάτων τους. Για παράδειγμα ¹⁰ ισχύουν οι παρακάτω πράξεις μεταξύ των αριθμών 45 = (101101) 2 και 24 = (011000) 2 : 45 & 24 = 101101 & 011000 = 001000 = 8, 45 24 = 111101 = 61, 45 ^ 24 = 110101 = 53. Οι τελεστές << και >> ολισθαίνουν τα bits του πρώτου τους ορίσματος προς τα αριστερά ή τα δεξιά αντίστοιχα τόσες φορές όσες το δεύτερό τους όρισμα. Π.χ. 45 << 1 = 101101 << 1 = 011010 ή 45 << 2 = 101101 << 2 = 110100. Τα bits που χάνονται όταν βγαίνουν από τα αριστερά κατά την αριστερή ολίσθηση χάνονται στα αλήθεια. Τα bits που μένουν κενά από τα δεξιά κατά την αριστερή ολίσθηση γίνονται μηδέν. Για μη προσημασμένους ακέραιους η πράξη της ολίσθησης αριστερά κατά 1 είναι ισοδύναμη με τον πολλαπλασιασμό με το 2, η ολίσθηση αριστέρα κατά 2 είναι ισοδύναμη με τον πολλαπλασιασμό με το 4 κ.ο.κ. Αντίστοιχα, όταν πραγματοποιείται ολίσθηση προς τα δεξιά, τα bits που βγαίνουν από το δεξί άκρο χάνονται. Τα bits που μένουν κενά από τα αριστερά γεμίζουν με μηδενικά. Η ολίσθηση προς τα δεξιά κατά μία θέση σε μη προσημασμένους ακεραίους είναι ισοδύναμη με την ακέραια διαίρεση με το δύο, η ολίσθηση κατά δύο θέσεις είναι ισοδύναμη με τη διαίρεση με το τέσσερα κ.ο.κ. Όλα αυτά είναι σχεδόν προφανή για τους μη προσημασμένους ακέραιους τύπους και σχετίζονται διαισθητικά με την πράξη του πολλαπλασιασμού και της διαίρεσης με το δύο αλλά τι γίνεται με τους προσημασμένους; Θυμηθείτε ότι σε μορφή συμπληρώματος ως προς δύο το πιο αριστερό bit παριστάνει το πρόσημο οπότε ο αριθμός (1111) 2 είναι το 1 σε έναν φανταστικό 4-bit υπολογιστή. Αν αυτό ολισθήσει δεξιά κατά 1 και το κενό που μένει αριστερά γεμίσει με το μηδέν, τότε ο αριθμός αυτός γίνεται (0111) 2 = 7 οπότε χάνεται το θέμα του πολλαπλασιασμού. Προκειμένου να μην εμπλακεί σε τέτοιου είδους διλήμματα τα οποία ίσως δεν έχουν και πρακτικό νόημα, το πρότυπο της C δεν ορίζει τι γίνεται σε περιπτώσεις ολίσθησης αρνητικών προσημασμένων ακέραιων. Οπότε τελικά, οι τελεστές αυτοί είναι φρόνιμο να χρησιμοποιούνται σε μη-προσημασμένους ακέραιους ¹⁰Στα παρακάτω παραδείγματα το ίσον χρησιμοποιείται με την έννοια των μαθηματικών και όχι ως ο τελεστής ανάθεσης τιμής της C. 12

τύπους. Τέλος, ο τελεστής συμπληρώματος ως προς ένα ~ αντιστρέφει τα bits του ορίσματός του, δηλαδή ~(1101) = 0010. 5.3 Συσχετιστικοί τελεστές Είναι οι τελεστές που χρησιμοποιούνται οπουδήποτε απαιτείται μία λογική συνθήκη η οποία είτε ισχύει είτε όχι. Μπορεί κανείς να τους θεωρήσει ως δυαδικούς τελεστές οι οποίοι επιστρέφουν τη λογική τιμή αληθής ή τη λογική τιμή ψευδής όποτε ισχύει μία συγκεκριμένη σχέση ανάμεσα στα δύο τους ορίσματα. Οι τελεστές φαίνονται στον πίνακα 5.3 Ένα σημείο που πρέπει να τονιστεί Πίνακας 3: Συσχετιστικοί τελεστές Τελεστής Σχέση Τελεστής Σχέση < Μικρότερο <= Μικρότερο ή ίσο > Μεγαλύτερο >= Μεγαλύτερο ή ίσο == Ίσο!= Διάφορο είναι ότι στην πραγματικότητα δεν υπάρχουν ιδιαίτερες τιμές για τις παραστάσεις αληθής και ψευδής. Η ακέραια τιμή 0 θεωρείται ότι σημαίνει ψευδής ενώ οποιαδήποτε μη-μηδενική ακέραια τιμή θεωρείται αληθής. Οπότε τελικά οι συσχετιστικοί τελεστές μπορούν να θεωρηθούν ως ειδικού τύπου αριθμητικοί τελεστές. Δηλαδή ο τελεστής < μπορούμε να θεωρήσουμε ότι είναι ένας αριθμητικός τελεστής που δίνει αποτέλεσμα 1 όταν το πρώτο του όρισμα είναι μικρότερο από το δεύτερο και 0 όταν αυτό δεν ισχύει. Επίσης μεγάλη προσοχή χρειάζεται και στον τελεστή ισότητας == τον οποίο μπορεί κανείς να μπερδέψει εύκολα με τον τελεστή απόδοσης τιμής =. Ο πρώτος ελέγχει αν τα δύο του ορίσματα είναι ίσα και επιστρέφει 1 αν είναι ή 0 αν δεν είναι. Ο τελεστής απόδοσης τιμής από την άλλη μεριά υπολογίζει την τιμή του δεύτερου ορίσματός του και το αποθηκεύει στη θέση μνήμης που αντιστοιχεί στο πρώτο όρισμα. Η πράξη αυτή θεωρείται ως έκφραση η οποία έχει τιμή ίση με την τιμή που τελικά παίρνει το αριστερό όρισμα. Οπότε αν κανείς θέλει να ελέγξει ότι η μεταβλητή a έχει την τιμή 5 και αντί να γράψει a == 5 γράψει a = 5 τότε η γλώσσα θα θεωρεί ότι αυτή η συνθήκη πάντα αληθεύει καθώς το 5 είναι μία μη-μηδενική τιμή οπότε αληθής. 5.4 Λογικοί τελεστές Λογικές εκφράσεις που προκύπτουν με τελεστές όπως αυτοί της προηγούμενης ενότητας μπορούν να συνδυαστούν με λογικούς τελεστές οι οποίοι είναι το λογικό ΚΑΙ &&, το λογικό Ή και το λογικό ΟΧΙ (λογική άρνηση)!. Για παράδειγμα η έκφραση a == 2 && b == 5 αληθεύει αν η a είναι ίση με 2 και η b είναι ίση με 5. Η έκφραση a == 2 b == 5 αληθεύει αν η a είναι ίση με 2 ή αν η b είναι ίση με 5. Τέλος ο λογικός τελεστής! αντιστρέφει τη λογική τιμή του ορίσματός του, δηλαδή αν μία έκφραση a είναι αληθής, τότε η!a είναι ψευδής και το αντίστροφο. Ο τελεστής! θέλει ιδιαίτερη προσοχή καθώς έχει υψηλότερη προτεραιότητα από τους συσχετιστικούς τελεστές 13

οπότε η έκφραση!a > -1 δεν σημαίνει!(a > -1) αλλά (!a) > -1 η οποία θα είναι πάντα αληθής ανεξάρτητα από την τιμή του a. 5.5 Τελεστές ανάθεσης Εκτός από τον απλό τελεστή ανάθεσης = υπάρχουν και οι τελεστές +=, -=, /=, *=, %=, &=, =, ^=, <<= και >>=. Ο τελεστής += για παράδειγμα προσθέτει στο πρώτο του όρισμα το δεύτερο, δηλαδή η εντολή a += 5; προσθέτει στη μεταβλητή a την τιμή 5. Είναι κατά κάποιο τρόπο μία συντόμευση της εντολής a = a + 5; που θα έγραφε κανείς σε μία πιο φιλική γλώσσα. Κατά αντίστοιχο τρόπο λειτουργούν και οι υπόλοιποι τελεστές. Μία ιδιαιτερότητα του τελετή απόδοσης τιμής στη C είναι ότι μπορεί να χρησιμοποιηθεί σε μία αλυσίδα αναθέσεων π.χ. σαν αυτήν: a = b = c = 5; η οποία εκτελείται από τα δεξιά προς τα αριστερά και έχει σαν αποτέλεσμα η τιμή 5 να αποθηκευτεί στη μεταβλητή c, στη συνέχεια η τιμής αυτής (5) να αποθηκευτεί στη b και στη συνέχεια η τιμή αυτής να αποθηκευτεί στην a. 5.6 Άλλοι τελεστές Υπάρχουν διάφοροι άλλοι τελεστές στη C (όχι πολλοί) όπως ο τελεστής κόμμα,, ο τελεστής απόδοσης τιμής υπό συνθήκη?, ο τελεστής sizeof, ο τελεστής [] για δεικτοδότηση πίνακα, ο τελεστής διεύθυνσης &, ο τελεστής αποαναφοροποίησης *, ο τελεστής μέλους struct. και ο τελεστής -> για τους οποίους θα μιλήσουμε αργότερα. 14