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



Σχετικά έγγραφα
Εισαγωγή στον Προγραμματισμό

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

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

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

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

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

Προεπεξεργαστής της C. C Preprocessor. Προγραμματισμός II 1

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

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

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

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

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

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

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

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

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

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

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

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

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

Προγραμματισμό για ΗΜΥ

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

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

Προεπεξεργαστής C. Προγραμματισμός Ι 1

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

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

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

Περιεχόμενα. Πρόλογος... 21

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

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

B. Ενσωμάτωση Ιθαγενών Μεθόδων

Περιεχόμενα. Πρόλογος... 17

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

Εξοικείωση με το πρόγραμμα DEV C++ Επικοινωνία Χρήστη - Υπολογιστή

ΕΡΓΑΣΤΗΡΙΟ 3: Προγραμματιστικά Περιβάλλοντα και το Πρώτο Πρόγραμμα C

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

ΕΡΓΑΣΤΗΡΙΟ 3: Προγραμματιστικά Περιβάλλοντα και το Πρώτο Πρόγραμμα C

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

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

Εισαγωγή στο Bison. Μεταγλωττιστές, Χειμερινό εξάμηνο

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Δομημένος Προγραμματισμός

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

Κεφάλαιο : Εισαγωγή στην C: (Διαλέξεις 3-4)

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

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

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

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

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

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

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

Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: ΕΠΛ 131 Αρχές Προγραµµατισµού I 3-2

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

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

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

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

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

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

Ασκήσεις σε Επαναληπτικούς Βρόχους και Συναρτήσεις. Επανάληψη για την ενδιάμεση εξέταση. (Διάλεξη 13)

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

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 3 Ο. Σταθερές-Παράμετροι-Μεταβλητές Αριθμητικοί & Λογικοί Τελεστές Δομή ελέγχου-επιλογής Σύνθετοι έλεγχοι

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ. Ασκήσεις Επανάληψης

Προγραμματισμός ΙI (Θ)

Εισαγωγή στον Προγ/μό Υπολογιστών

Κεφάλαιο 2.6: Είσοδος / Έξοδος Δεδομένων, Μορφοποίηση Δεδομένων Εξόδου. (Διάλεξη 7) Είσοδος/ Έξοδος

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

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

Κεφάλαιο 2.6: Είσοδος / Έξοδος Δεδομένων, Μορφοποίηση Δεδομένων Εξόδου. (Διάλεξη 7)

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

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

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

ΤΕΜ-101 Εισαγωγή στους Η/Υ Εξεταστική Ιανουαρίου 2011 Θέματα Β

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

ΜΕΤΑΓΛΩΤΤΙΣΤΕΣ. Στην εξοικείωση με τη διαδικασία κατασκευής ενός Λεξικού Αναλυτή κάνοντας χρήση του lex.

H ΓΛΩΣΣΑ C. Μάθηµα 1: Το Πρώτο µας Πρόγραµµα σε C. ηµήτρης Ψούνης

Επανάληψη για τις Τελικές εξετάσεις. (Διάλεξη 24) ΕΠΛ 032: ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΕΘΟΔΩΝ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

ΗΥ-150. Προγραµµατισµός. Εντολές Ελέγχου Ροής

Λειτουργικά. Συστήματα Ι. Φ ρ ο ν τ ι σ τ ή ρ ι ο. Αριστείδης Ηλίας. Εργαστήριο Ηλεκτρονικών Υπολογιστών

Συναρτήσεις και διαδικασίες

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

Κεφάλαιο 3.1, : Συναρτήσεις I. (Διάλεξη 11)

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

Τυπικές χρήσεις της Matlab

Εργαστήριο 08 Εισαγωγή στo Yacc

ΕΡΓΑΣΤΗΡΙΟ 6: Συναρτήσεις και Αναδρομή

Κεφάλαιο 4: Συνθήκες Έλεγχου (if-else, switch) και Λογικοί τελεστές / παραστάσεις. (Διάλεξη 8)

Κεφάλαιο 2.6: Είσοδος / Έξοδος εδοµένων, Μορφοποίηση εδοµένων Εξόδου. ( ιάλεξη 7) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

ΚΕΦΑΛΑΙΟ 9 ΒΑΣΙΚΕΣ ΕΝΤΟΛΕΣ

Εισαγωγή στον δομημένο προγραμματισμό

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

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

Κεφάλαιο Αλφαριθμητικές Σειρές Χαρακτήρων (Strings) (Διάλεξη 20) 1) Strings στη C

Δυναμικές Ιστοσελίδες Εισαγωγή στην Javascript για προγραμματισμό στην πλευρά του client

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

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

Διάλεξη 6: Δείκτες και Πίνακες

Υπολογισμός - Εντολές Ελέγχου

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

Παρακάτω δίνεται o σκελετός προγράμματος σε γλώσσα C. Σχολιάστε κάθε γραμμή του κώδικα.

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (2)

Transcript:

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

Διαδικασία Μεταγλώττισης πρόγραµµα επεξεργασίας κειµένου if a<b (lib ref) do while z = x-y (lib ref) προεπεξεργαστής if a<b (lib ref) do while z = x-y (lib ref) Πηγαίος Κώδικας Επεξεργασµένος Κώδικας 01100100 11011010 11001001 00010001 11110001 πρόγραµµα σύνδεσης 01100100 (lib ref) 11001001 00010001 (lib ref) µεταγλωττιστής Εκτελέσιµο Αρχείο Κώδικας Αντικειµένου 01100101 00010111 10001001 11011010 11110001 Βιβλιοθήκη Χαροκόπειο Πανεπιστήμιο 2/42

Ο προεπεξεργαστής Ο προεπεξεργαστής αλλάζει το πρόγραμμα μας, ανάλογα με τις εντολές που αρχίζουν με #. Η έξοδος του είναι ενα άλλο πρόγραμμα γλώσσας C. Το πρόγραμμα αυτό δεν το βλέπουμε επειδή δίνεται αυτόματα στον μεταγλωττιστή. Χαροκόπειο Πανεπιστήμιο 3/42

#include Η εντολή #include λέει στον προεπεξεργαστή να αντικαταστήσει την εντολή με τα περιεχόμενα του αρχείου που ακολουθεί. Χαροκόπειο Πανεπιστήμιο 4/42

#include 1 #include < s t d i o. h> 2 3 int main ( ) 4 { 5 printf ( "Hello world!\n" ) ; 6 } Ο προεπεξεργαστής βρίσκει το αρχείο stdio.h που βρίσκεται σε κάποια προκαθορισμένη θέση στο σύστημα αρχείων και αντικαθιστά την γραμμή 1 με το περιεχόμενο του αρχείου αυτού. Χαροκόπειο Πανεπιστήμιο 5/42

#include Το πρόγραμμα που τελικά φτάνει στον μεταγλωττιστή είναι: 1 #ifndef _STDIO_H 2 3 #if! defined need_file &&! defined need FILE 4 # define _STDIO_H 1 5 # include < f e a t u r e s. h> 6 7 / * a l o t o f code here * / 8 10 9 #endif / * < s t d i o. h> included. * / 11 #endif / *! _STDIO_H * / 12 13 int main ( ) 14 { 15 printf ( "Hello world!\n" ) ; 16 } Χαροκόπειο Πανεπιστήμιο 6/42

#include Εκτός από την προηγούμενη μορφή, μπορούμε να κάνουμε: 1 #include "myheader.h" 2 3 int main ( ) 4 { 5 printf ( "Hello world!\n" ) ; 6 } Σε αυτή την μορφή ο προεπεξεργαστής προσθέτει στους φακέλους που ψάχνει το αρχείο myheader.h και τον τρέχον φάκελο (τον φάκελο που βρίσκεται το πρόγραμμα μας). Αφού βρεθεί το αρχείο myheader.h το περιεχόμενα του αντικαθιστούν την εντολή include. Χαροκόπειο Πανεπιστήμιο 7/42

#define Αντικαταστάσεις και Συμβολικά Ονόματα Ο προεπεξεργαστής μας επιτρέπει να κάνουμε αντικαταστάσεις λέξεων στα προγράμματα μας. Με την εντολή #define PRINTFUNCTION p r i n t f λέμε για παράδειγμα στον προεπεξεργαστή να αντικαταστήσει το αναγνωριστικό PRINTFUNCTION με την λέξη printf όπου αυτή εμφανίζεται στον κώδικα. Χαροκόπειο Πανεπιστήμιο 8/42

#define Συμβολικά Ονόματα 1 #include <stdio. h> 2 3 #define PRINTFUNCTION p r i n t f 4 5 int main ( ) 6 { 7 PRINTFUNCTION ( "Hello world\n" ) ; 8 } Το παραπάνω πρόγραμμα αντικαθίσταται με το 1 #include <stdio. h> 2 3 int main ( ) 4 { 5 printf ( "Hello world\n" ) ; 6 } πριν δωθεί στον μεταγλωττιστή για μεταγλώττιση. Χαροκόπειο Πανεπιστήμιο 9/42

#define Συμβολικά Ονόματα και Σταθερές Η πιο συνηθισμένη χρήση είναι η απόδοση συμβολικών ονομάτων σε αριθμητικές σταθερές: #define BUFFER_SIZE 1024 #define PI 3.1459 Ο προεπεξεργαστής θα αναγνωρίσει και θα αντικαταστήσει το συμβολικό όνομα με την δοσμένη τιμή. Η εντολή: foo = ( char * ) malloc ( BUFFER_SIZE ) ; θα γίνει foo = ( char * ) malloc ( 1 0 2 4 ) ; μετά την προεπεξεργασία. Χαροκόπειο Πανεπιστήμιο 10/42

#define Συμβολικά Ονόματα και Σταθερές Κατά σύμβαση τα ονόματα μακροεντολών είναι με κεφαλαία για να μπορούμε με μια ματιά να ξεχωρίσουμε τις μακροεντολές από τις μεταβλητές. Χαροκόπειο Πανεπιστήμιο 11/42

Πολλαπλές Γραμμές Στην πιο απλή μορφή μια εντολή στον προεπεξεργαστή τελειώνει με το τέλος της γραμμής. Άμα θέλουμε να συνεχίζει μπορούμε να χρησιμοποιήσουμε ενα backslash. 1 #define NUMBERS 1, \ 2 2, \ 3 3 4 5 int x [ ] = { NUMBERS } ; Το παραπάνω κομμάτι κώδικα είναι ισοδύναμο με 1 int x [ ] = { 1, 2, 3 } ; Χαροκόπειο Πανεπιστήμιο 12/42

Συνήθη Λάθη Χρήστη του = 1 #define VALUE = 100 2 3 if ( i == VALUE ) 4 { 5 / * some code here * / 6 } οδηγεί στο πρόγραμμα 1 if ( i == = 100 ) 2 { 3 / * some code here * / 4 } Το οποίο δεν περνάει από τον μεταγλωττιστή. Χαροκόπειο Πανεπιστήμιο 13/42

Συνήθη Λάθη Χρήση του ; 1 #define VALUE 100; 2 3 if ( i == VALUE ) 4 { 5 / * some code here * / 6 } οδηγεί στο πρόγραμμα 1 if ( i == 100; ) 2 { 3 / * some code here * / 4 } Το οποίο δεν περνάει από τον μεταγλωττιστή. Χαροκόπειο Πανεπιστήμιο 14/42

Αντικατάσταση μακροεντολών Ο προεπεξεργαστής επεξεργάζεται το πρόγραμμά σας και αντικαθιστά τα συμβολικά ονόματα σειριακά, μετά το σημείο που εμφανίζεται η #define. π.χ foo = X ; #define X 100 bar = X ; foo = X ; bar = 100; Χαροκόπειο Πανεπιστήμιο 15/42

Αντικατάσταση μακροεντολών Αντικατάσταση της αντικατάστασης Η αντικατάσταση ερευνάται και αυτή για αντικατάσταση. π.χ #define TABLESIZE BUFSIZE #define BUFSIZE 1024 int buffer [ TABLESIZE ] ; int buffer [ 1 0 2 4 ] ; Σε όλον τον κώδικα: αρχικά το TABLESIZE θα αντικατασταθεί με το BUFSIZE και κατόπιν το BUFSIZE με το 1024. Προσέξτε ότι το BUFSIZE δεν ορίζεται, οταν χρησιμοποιείται, απλά αντικαθίσταται με το αλφαριθμητικό. Χαροκόπειο Πανεπιστήμιο 16/42

#define Μακροεντολές συναρτήσεων Είναι δυνατό να ορίσουμε μακροεντολές που μοιάζουν με κλήση συνάρτησης: 1 #include < s t d i o. h> 2 3 #define h e l l o ( ) p r i n t f ( "Hello world\n" ) ; 4 5 int main ( ) 6 { 7 hello ( ) ; 8 } Προσοχή οι παρενθέσεις είναι υποχρεωτικές και δεν πρέπει να υπάρχει κενό μεταξύ του ονόματος και των παρενθέσεων. Χαροκόπειο Πανεπιστήμιο 17/42

#define Μακροεντολές με ορίσματα Οι μακροεντολές μπορούν να πάρουν και ορίσματα: Τα ορίσματα πρέπει να είναι identifiers της C και να χωρίζονται από κόμματα και προαιρετικά κενά. Όλος ο ορισμός πρέπει να είναι σε μια λογική γραμμή. π.χ η μακροεντολή #define min ( x, y ) ( ( x ) <( y )? ( x ) : ( y ) ) αλλάζει όπως παρακάτω: x = min(a,b); x = ((a)<(b)?(a):(b )); y = min(1,2); y = ((1)<(2)?(1):(2)); z = min(a+28,*p); y = ((a+28)<(*p)?(a+28):(*p)); Χαροκόπειο Πανεπιστήμιο 18/42

Λάθη στα Ορίσματα Προσοχή γιατί στις μακροεντολές δεν γίνεται συντακτικός έλεγχος. Προσοχή με τις προτεραιότητες μετά την αντικατάσταση. #define assign ( a, b ) a = ( char ) b Έτσι το assign ( x, y>>8) γίνεται x = ( char ) y> >8; Χαροκόπειο Πανεπιστήμιο 19/42

Λάθη στα Ορίσματα Προτεραιότητα Προσοχή γιατί η παρακάτω μακροεντολή #define RADTODEG( x ) ( x * 57.29578) γίνεται RADTODEG(a+b) που δεν είναι σωστή. (a+b*57.29578) Χαροκόπειο Πανεπιστήμιο 20/42

Λάθη στα Ορίσματα Προτεραιότητα Προσοχή γιατί η παρακάτω μακροεντολή #define RADTODEG( x ) ( x ) * 57.29578 γίνεται 1 / RADTODEG(a) 1 / (a) * 57.29578 που δεν είναι σωστή. Χαροκόπειο Πανεπιστήμιο 21/42

Αντικατάσταση Ορισμάτων Όλα τα ορίσματα σε μια μακροεντολή αντικαθιστώνται πριν γίνει η τελική αντικατάσταση: αφού αντικατασταθούν τα ορίσματα, όλο το κείμενο της μακροεντολής σκανάρεται και για άλλες αντικαταστάσεις (και τα ορίσματα!) μπορεί να φαίνεται περίεργο, αλλά είναι χρήσιμο για να συμπεριφέρονται οι μακροεντολές όπως οι κλήσεις συνάρτησης π.χ έστω η μακροεντολή #define min ( x, y ) ( ( x ) <( y )? ( x ) : ( y ) ) Ο κώδικας min(min(a,b),c) γίνεται min(((a)<(b)?(a):(b )), c) και μετά (((( a)<(b)?(a):(b)))<(c)?(((a)<(b)?(a):(b ))):( c)) Χαροκόπειο Πανεπιστήμιο 22/42

Παράλειψη Ορισμάτων Σε μια μακροεντολή μπορούμε να αφήσουμε ένα η περισσότερα ορίσματα κενά. ο προεπεξεργαστής χτυπάει άμα δεν δώσουμε σωστό αριθμό ορισμάτων εαν έχω 2 ορίσματα πρέπει να έχω ακριβώς ένα κόμμα μέσα στις παρενθέσεις Προσοχή στις αντικαταστάσεις:.1 min(,b) (( )<(b)?( ):( b)).2 min(,) (( )<( )?( ):( )).3 min ((,),) (((,))<( )?((,)):( )).4 min() λάθος.5 min(,,) λάθος Χαροκόπειο Πανεπιστήμιο 23/42

Αποφυγή Αντικατάστασης Για να αποφύγουμε την αντικατάσταση μπορούμε να γράψουμε μια παράμετρο μέσα σε διπλά εισαγωγικά "". π.χ #define foo ( x ) x, "x" Η χρήση της foo(bar) έχει ως αποτέλεσμα: bar, "x" και όχι bar, "bar" Χαροκόπειο Πανεπιστήμιο 24/42

Προκαθορισμένες Συμβολικές Σταθερές FILE Αντικαθίσταται με το όνομα και το path του τρέχοντος αρχείου που επεξεργαζόμαστε Είναι σταθερά αλφαριθμητικού π.χ "/usr/include/stdio.h" LINE Αντικαθίσταται με τον αριθμό γραμμής του τρέχοντος αρχείου Πολύ χρήσιμες σταθερές για μηνύματα λάθους, π.χ fprintf ( stderr, "Error at file %s, line number %d\n", \ FILE, LINE ) ; Χαροκόπειο Πανεπιστήμιο 25/42

Προκαθορισμένες Συμβολικές Σταθερές DATE Αντικαθίσταται με την τρέχουσα ημερομηνία "Feb 2 1996" TIME Αντικαθίσταται με την τρέχουσα ώρα "23:59:59" Χαροκόπειο Πανεπιστήμιο 26/42

Τελεστής # Για να δημιουργήσουμε strings από παραμέτρους μακροεντολής μπορούμε να γράψουμε: #define QUOTEME( x ) #x ο κώδικας printf ( "%s\n", QUOTEME ( 1 + 2 ) ) ; γίνεται printf ( "%s\n", "1+2" ) ; Χαροκόπειο Πανεπιστήμιο 27/42

Τελεστής # Για να βάλουμε εισαγωγικά στην τιμή μιας άλλης μακροεντολής μπορούμε να κάνουμε: #define _QUOTEME( x ) #x #define QUOTEME( x ) _QUOTEME( x ) Η τεχνική αυτή βολεύει για παράδειγμα όταν θέλουμε να βάλουμε εισαγωγικά στην μακροεντολή LINE. Στην γραμμή 34 του κώδικα.1 QUOTEME( LINE ) "34".2 _QUOTEME( LINE ) " LINE " Χαροκόπειο Πανεπιστήμιο 28/42

Τελεστής ## Συνένωση Συμβόλων Πολλές φορές υπάρχει ανάγκη να ενώσει κανείς 2 σύμβολα (π.χ αλφαριθμητικά) όταν αντικαθίσταται μια μακροεντολή. Μπορούμε να γράψουμε: #define concat ( x, y ) x##y Τα δύο σύμβολα αριστερά και δεξιά του τελεστή θα ενωθούν σε ένα. Τα σύμβολα αυτά συνήθως είναι: identifiers( π.χ μεταβλητές) identifiers και αριθμοί ( π.χ foo3 ) αριθμοί ( π.χ 1 και 3 σε 13 ) Χαροκόπειο Πανεπιστήμιο 29/42

Τελεστής ## Παράδειγμα Συνένωσης Συμβόλων struct command { char *name ; void ( * function ) (void ) ; } ; struct command commands [ ] = { { "quit", quit_command }, { "help", help_command },... } ; #define COMMAND(NAME) \ { #NAME, NAME ## _command } struct command commands [ ] = { COMMAND (quit ), COMMAND (help ),... } ; Χαροκόπειο Πανεπιστήμιο 30/42

Μεταγλώττιση υπό Συνθήκες Ο προεπεξεργαστής μας επιτρέπει να μεταγλωττίσουμε επιλεκτικά κάποια κομμάτια κώδικα με την χρήση των εντολών #ifdef και #ifndef. 1 int foo ( ) 2 { 3 #ifdef DEBUG 4 fprintf (stderr, "foo() called..\n" ) ; 5 #endif 6 7 / * code here * / 8 } Η εντολή fprintf() μεταγλωττίζεται μόνο εαν έχουμε κάνει define την σταθερά DEBUG. Χαροκόπειο Πανεπιστήμιο 31/42

Μεταγλώττιση υπό Συνθήκες Με την χρήση της #ifdef μπορούμε να κάνουμε επιλεκτική μεταγλώττιση. Μας βοηθάει πολύ όταν θέλουμε ο κώδικας μας να λειτουργεί σε διάφορα λειτουργικά που έχουν διαφορετικές συναρτήσεις. 1 int foo ( ) 2 { 3 #ifdef SYSTEM_IS_WINDOWS 4 / * windows s p e c i f i c code * / 5 #elif SYSTEM_IS_LINUX 6 / * l i n u x s p e c i f i c code * / 7 #else 8 / * code f o r o t h e r cases * / 9 #endif 10 } Χαροκόπειο Πανεπιστήμιο 32/42

Αρχεία Επικεφαλίδας Η τεχνική αυτή μας βοηθάει ώστε να μην κάνουμε #include το ίδιο αρχείο πολλές φορές. Παρακάτω φαίνεται μια δυνητική μορφή του stdio.h. 1 #ifndef STDIO_H 2 #define STDIO_H 3 4 / * contents o f STDIO_H * / 5 6 #endif Την δεύτερη φορά που θα γίνει #include το αρχείο αυτό, θα έχει γίνει define η σταθερά STDIO_H και άρα ο κώδικας δεν θα συμπεριληφθεί. Χαροκόπειο Πανεπιστήμιο 33/42

Το παράδειγμα των assertions Η βιβλιοθήκη της C μας παρέχει το αρχείο επικεφαλίδας assert.h το οποίο παρέχει την μακροεντολή assert(). η μακροεντολή αυτή πέρνει ως παράμετρο μια συνθήκη εαν η συνθήκη είναι αληθής δεν κάνει τίποτα εαν η συνθήκη είναι ψευδής τότε σταματάει την εκτέλεση του προγράμματος και μας ενημερώνει για το σημείο και την συνθήκη Η μακροεντολή assert() βολεύει πολύ όταν κάνουμε debugging. Χαροκόπειο Πανεπιστήμιο 34/42

Το παράδειγμα των assertions 1 #include <stdio. h> 2 #include <assert. h> 3 4 double divide ( int a, int b ) 5 { 6 assert ( b!= 0 ) ; 7 return ( ( double ) a ) / b ; 8 } 9 10 int main ( ) 11 { 12 printf ( "3/2 = %lf\n", divide (3, 2 ) ) ; 13 printf ( "3/2 = %lf\n", divide (3, 0 ) ) ; 14 } Το παραπάνω πρόγραμμα τυπώνει 3/2 = 1.500000 test: test.c:6: double divide(int, int): Assertion `b!= 0' failed. Aborted Χαροκόπειο Πανεπιστήμιο 35/42

Το παράδειγμα των assertions Οι έμπειροι προγραμματιστές βάζουν assertions στον κώδικα τους σε σημεία που θέλουν να ελέγξουν πως κάποια συνθήκη είναι αλήθεια. Όταν θέλουμε να δώσουμε όμως το κώδικα σε μορφή τελικού προϊόντος σε κάποιον πελάτη, ο κώδικας των assertions καθυστερεί την εκτέλεση. Για αυτό εάν έχουμε δηλώσει την σταθερά NDEBUG πριν την εισαγωγή του assert.h στον κώδικα μας η μακροεντολή assert() ορίζεται ως: #define a s s e r t ( i g n o r e ) ( ( void ) 0) Ο μεταγλωττιστής είναι έξυπνος αρκετά ώστε να αφαιρέσει αυτές τις περιττές εντολές από τον κώδικα. Χαροκόπειο Πανεπιστήμιο 36/42

#if Η εντολή #if επιτρέπει τον έλεγχο για μια τιμή, αντί για ύπαρξη μιας μακροεντολής. #if expression controlled text #endif Η έκφραση expression μπορεί να περιέχει:.1 ακέραιους και χαρακτήρες.2 αριθμητικούς τελεστές για πράξεις (και κατά bit), συγκρίσεις, λογικούς τελεστές.3 μακροεντολές.4 την εντολή defined (θα την δούμε παρακάτω).5 identifiers (αν δεν είναι μακροεντολές παίρνουν τιμή 0) Χαροκόπειο Πανεπιστήμιο 37/42

Η εντολή defined Χρησιμοποιείται με τα #if και #elif για να ελέγξει αν ένα σύμβολο είναι ορισμένο ως μακροεντολή: defined name και defined (name) είναι εκφράσεις που παίρνουν την τιμή 1 αν το name είναι ορισμένο ως μακροεντολή μέχρι το τρέχον σημείο του προγράμματος, αλλιώς παίρνουν την τιμή 0 η έκφραση #if defined MACRO είναι ισοδύναμη με την #ifdef MACRO Χαροκόπειο Πανεπιστήμιο 38/42

Παραδείγματα #if και defined #if defined ( vax ) defined ( ns16000 ) / / code here #endif ή #if defined BUFSIZE && BUFSIZE >= 1024 / / code here #endif Το τελευταίο παράδειγμα είναι ισοδύναμο με #if BUFSIZE >= 1024 / / code here #endif αφού στην περίπτωση που το BUFSIZE δεν έχει οριστεί θα γίνει 0. Χαροκόπειο Πανεπιστήμιο 39/42

#error Η μακροεντολή #error εισάγει ένα μήνυμα λάθους στην έξοδο του μεταγλωττιστή. π.χ #error "NO!" τυπώνει το μήνυμα στην έξοδο του μεταγλωττιστή και σταματάει την εκτέλεση του. Πολύ χρήσιμη μακροεντολή για να δούμε εάν εκτελείται ένα κομμάτι κώδικα. Χαροκόπειο Πανεπιστήμιο 40/42

Παράδειγμα #error #ifdef WINDOWS... / * Windows s p e c i f i c code * / #elif defined ( UNIX )... / * Unix s p e c i f i c code * / #else #error "What's your operating system?" #endif Χαροκόπειο Πανεπιστήμιο 41/42

#pragma Η μακροεντολή #pragma επιτρέπει στον κατασκευαστή ενός μεταγλωττιστή να παραμετροποιεί τον μεταγλωττιστή του. Με αυτό τον τρόπο ο προγραμματιστής έχει μεγαλύτερο έλεγχο πάνω στον μετααγλωττιστή. Για παράδειγμα η μακροεντολή αυτή χρησιμοποιείται συνήθως για να μην εμφανίζονται συγκεκριμένα μηνύματα λάθους του μεταγλωττιστή, κ.τ.λ π.χ ο μεταγλωττιστής gcc παρέχει την #pragma message #pragma message "Compiling " FILE "..." που τυπώνει μηνύματα αλλά δεν σταματάει την μεταγλώττιση. Χαροκόπειο Πανεπιστήμιο 42/42