(programming interfaceή/και application programming interface API).

Σχετικά έγγραφα
Μεταγλώττιση και σύνδεση πολλαπλών αρχείων κώδικα. Προγραμματισμός II 1

Βιβλιοθήκες Αφηρημένοι τύποι δεδομένων. Προγραμματισμός II 1

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

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

Πξνγξακκαηηζκόο Ι (ΗΥ120)

Το λειτουργικό σύστημα. Προγραμματισμός II 1

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

Το λειτουργικό σύστημα. Προγραμματισμός II 1

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

make Προγραμματισμός II 1

Το λειτουργικό σύστημα. Προγραμματισμός II 1

CE121 Προγραµµατισµός 2. Εισαγωγή σε Makefiles. CE121 -

CE121 Προγραµµατισµός 2. Εισαγωγή σε Makefiles. CE121 -

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

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

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

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

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

int a[5]; a[0] a[1] a[2] a[3] a[4] 15/10/2009

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

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

Α. Ερωτήσεις Ανάπτυξης

Διάλεξη 22η: Επιπλέον στοιχεία της C

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

Κεφάλαιο 8.7. Πίνακες & Συναρτήσεις ( ιάλεξη 17) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

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

Κεφάλαιο 7 : Είδη, Τεχνικές, και Περιβάλλοντα Προγραµµατισµού

Οι δείκτες στη γλώσσα C

Η Γλώσσα Προγραµµατισµού C++ (The C++ Programming Language) Ιστοσελίδα του µαθήµατος. Περιεχόµενα. ηµήτριος Κατσαρός, Ph.D. Κλάσεις.

Η Γλώσσα Προγραµµατισµού C++ (The C++ Programming Language)

ΚΕΦΑΛΑΙΟ 7 ΕΙ Η, ΤΕΧΝΙΚΕΣ ΚΑΙ ΠΕΡΙΒΑΛΛΟΝΤΑ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

double sum(double a, double b) { return(a+b); } double my_avg(double a, double b) { return(sum(a, b)/2.0); }

Αντικειµενοστρεφής Προγραµµατισµός

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

ΠΛΗ111. Ανοιξη Μάθηµα 1 ο Ανασκόπηση της Γλώσσας Προγραµµατισµού C. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Επεξεργασία Αρχείων Κειµένου

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

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

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

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

Βαθμός Σχόλια. lab5 PASS PASS PASS PASS PASS. Οριακά PASS - Καλή δουλειά

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

2η Προγραµµατιστική Εργασία

Ενότητες στην C Τεχνική Υλοποίησης Αφαιρετικών Τύπων Δεδομένων στην C

ΑΦAΙΡΕΤΙΚΟΣ (ή ΑΦΗΡΗΜΕΝΟΣ) ΤΥΠΟΣ ΔΕΔΟΜΕΝΩΝ (ΑΤΔ) (Abstract Data Type-ADT) - σύνολο δεδομένων (data, objects) - σύνολο πράξεων στα δεδομένα

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

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

Πληροφορική 2. Γλώσσες Προγραμματισμού

Κεφάλαιο : Εισαγωγή στην C. ( ιαλέξεις 3-4) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

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

είκτες και Πίνακες (2)

ΤΥΠΟΣ ΔΕΔΟΜΕΝΩΝ (ΑΤΔ) (Abstract Data Type-ADT)

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

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

lab13grades 449 PASS 451 PASS PASS FAIL 1900 FAIL Page 1

ΕΡΓΑΣΙΑ ΕΞΑΜΗΝΟΥ - ΜΕΡΟΣ Γ'

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

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

ύο βασικές ιδέες Ενότητες Απόκρυψη Πληροφορίας, Αφηρηµένοι Τύποι εδοµένων 1) ιαχώρισε το πρόβληµα σεµικρότερα καλώς καθορισµένα υπο-προβλήµατα

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

Μεθόδων Επίλυσης Προβλημάτων

ΕΙΔΗ,ΤΕΧΝΙΚΕΣ ΚΑΙ ΠΕΡΙΒΑΛΛΟΝΤΑ ΠΡΟΓΡΑΜΜΑΤΙ- ΣΜΟΥ

οµές (structures) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: Πίνακες δοµών, δείκτες σε δοµές, και αυτοαναφορικές δοµές.

Διάλεξη 2η: Αλγόριθμοι και Προγράμματα

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

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ II. Υφαντόπουλος Νικόλαος Υποψήφιος Διδάκτορας Contact:

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

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

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

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

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

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

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

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

Προγραμματισμός Υπολογιστών με C++

Γλώσσες υψηλού επιπέδου Περιέχουν περισσότερες εντολές για την εκτέλεση πολύπλοκων εργασιών Τα προγράµµατα µεταφράζονται σε γλώσσα µηχανής είτε από το

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

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

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 15/11/09, 23:59

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

Περιεχόµενα. 1 Εισαγωγή στις οµές εδοµένων 3. 2 Στοίβα (Stack) 5

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

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

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

που θα δώσει αποτέλεσµα 48, λόγω της αριστερής προσεταιριστικότητας των τελεστών / και *, ενώ η επιθυµητή αντικατάσταση θα ήταν η

2.1 Αντικειµενοστρεφής προγραµµατισµός

Κλάσεις και Αντικείµενα

Κεφάλαιο 10 ο Υποπρογράµµατα

BloodShed Dev C++ Οδηγίες Χρήσης (Συγγραφέας: Πάρις Πολύζος)

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

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

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

ΚΑΤΑΣΚΕΥΑΣΤΕΣ ΑΝΤΙΓΡΑΦΗΣ

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

lab7 PASS -Δεν έχεις καθόλου σχόλια! Διάβασε το φυλλάδιο. PASS -Πολύ καλή εργασία µε σωστά και επεξηγηµατικά σχόλια. -Πρόσεξε την στοίχισή σου!

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

Κεφάλαιο Αλφαριθµητικές Σειρές Χαρακτήρων (Strings)

ΑΣΚΗΣΗ 1. Structural Programming

Προγραμματισμός Συστημάτων

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

Transcript:

Προγραµµατισµός Ι (ΗΥ120) ιάλεξη 21: Μεταγλώττιση και σύνδεση πολλαπλών αρχείων κώδικα - Βιβλιοθήκες

Επαναχρησιµοποίηση κώδικα Μεγάλο «στοίχηµα» στην βιοµηχανία λογισµικού. Ιδανικά, δεν χρειάζεται να ξαναγράψουµε κώδικα που έχει ήδη γραφτεί (από κάποιους άλλους). Πώς χρησιµοποιούµε κώδικα που υπάρχει; Προσέγγιση Α:αντιγράφουµετον πηγαίο κώδικα, κάνοντας ίσως προσαρµογές για τις ανάγκες µας. Προσέγγιση Β:καλούµετον εκτελέσιµο κώδικα, περνώντας τις παραµέτρους που χρειάζονται σύµφωνα µε τις οδηγίες χρήσης / περιγραφή λειτουργικότητας του. Το Β απαιτεί µηχανισµό σύνδεσης κώδικα που έχει ήδη µεταφραστεί µε τον κώδικα που γράφουµε. 2

οµηµένη ανάπτυξη συστηµάτων Ο κώδικας ενός πολύπλοκου συστήµατος αναπτύσσεται σταδιακά, «χτίζοντας» νέα λειτουργικότητα πάνω στην ήδη υπάρχουσα. Πωςχρησιµοποιούµευπάρχουσα λειτουργικότητα; Mέσω της αντίστοιχης διεπαφής προγραµµατισµού (programming interfaceή/και application programming interface API). Στο υλικό αυτό γίνεται µέσω της αντίστοιχης φυσικής διεπαφής (physical interface): π.χ. πινάκια, καλώδια. Πρέπει να τηρούνται πολύ συγκεκριµένοι κανόνες αλληλεπίδρασης, σύµφωναµε τις αντίστοιχες προδιαγραφές χρήσης. 3

0A1F68CED90B3020D85F1397C 5D90A3120D35F1197FFFF0131 D28CEB95F3420C85C11100 00B19D5711C210AA00B5A911F F2F8D9C5B3B20B851A0AC10 4 void init(int); int rnd(); hardware interface software interface

hardware documentation 5 void init(int); /* initialize random number generator with a seed; call once, before rnd */ int rnd(void); /* returns next random number */ software documentation

ιεπαφή Λογισµικού Αποτελείται (κυρίως) από δηλώσεις σταθερών, µεταβλητών και συναρτήσεων. Κάθε συνάρτηση χρησιµεύει για ένα συγκεκριµένο σκοπό π.χ. την εκτέλεση κάποιας λειτουργικότητας. Η σηµασία / κωδικοποίηση των παραµέτρων και λειτουργικότητα των συναρτήσεων ορίζεται µέσω κατάλληλων προδιαγραφών (τεκµηρίωση). Για να χρησιµοποιήσουµε ένα τµήµα λογισµικού, πρέπει Να το συνδέσουµε κατάλληλα µε το πρόγραµµα µας Να «καλούµε» τις συναρτήσεις σύµφωνα µε τις προδιαγραφές. 6

Η Λογική του Μαύρου Κουτιού (Black Box) Μας ενδιαφέρει είναι η λειτουργικότητατου κώδικα που χρησιµοποιούµε Όχι οι «εσωτερικές» λεπτοµέρειες υλοποίησης της. Λογική του black-box: γνωρίζουµε το πως πρέπει να χρησιµοποιήσουµε κάτι χωρίςαπαραίτητα να γνωρίζουµε και το πως (ακριβώς) αυτό «δουλεύει». Π.χ. όταν οδηγούµε, αλλάζουµε ταχύτητες µε τον µοχλό ταχυτήτων σύµφωνα µε κάποιους απλούς(;) κανόνες χωρίςνα γνωρίζουµε το πως λειτουργεί εσωτερικά ο µηχανισµός επιλογής / µετάδοσης. Π.χ. χρησιµοποιούµε µια συνάρτηση µε βάση την περιγραφή της λειτουργικότητας της (manuals) χωρίς να γνωρίζουµε το πως αυτή υλοποιείται. 7

διεπαφή χρήσης 8 εσωτερική υλοποίηση λειτουργικότητας (που δεν βλέπει ο εξωτερικός παρατηρητής/χρήστης) περιγραφή διεπαφής (οδηγίες χρήσης) black box

9 υλοποίηση συστήµατος διεύθυνσης περιγραφή διεπαφής οι τροχοί στρίβουν προς την κατεύθυνση που στρίβεις το τιµόνι black box

P1x compiler x -> y P1 y 10 P2x compiler x -> y P2 y P1 y P2 y linker P y CPU y

P1 P linker P1 P 11 P2 P linker P2 P P3 P linker P3 P

P1 linker P1 12 P P2 linker P2 P P P3 linker P3 P

Ανάπτυξηαυτόνοµων τµηµάτων λογισµικού Σχεδίαση προγραµµατιστικής διεπαφής: αποφασίζουµε το πως θα χρησιµοποιηθεί (προγραµµατιστικά) η λειτουργικότητα. Κατασκευή header file:ορισµός της διεπαφής µε την µορφή ενός header fileπου θα χρησιµοποιηθεί (κυρίως) από τα προγράµµατα «πελάτες». Κατασκευή υλοποίησης:σε ξεχωριστό αρχείο υλοποιούµε τη λειτουργικότητα, όπως ορίζεται στο header file, που µεταφράζεται για να δηµιουργηθεί το τµήµα κώδικα που θα συνδεθεί (αργότερα) µε τον κώδικα από τα προγράµµατα «πελάτες». 13

Header filesστην C Η διεπαφή προγραµµατισµού στην C ορίζεται µέσω ενός header file, που περιέχει (α) ορισµούς τύπων δεδοµένων, (β) δηλώσεις σταθερών και καθολικών µεταβλητών, και (γ) δηλώσεις συναρτήσεων. Οι δηλώσεις µεταβλητών και συναρτήσεων πρέπει να έχουν τον προσδιορισµόextern, υποδεικνύοντας στον µεταγλωττιστή ότι οι αντίστοιχες υλοποιήσεις τους δεν βρίσκονται απαραίτητα στο ίδιο αρχείο. Κάνοντας #includeένα header file, το πρόγραµµα µπορεί να χρησιµοποιείτύπους, µεταβλητές και συναρτήσεις που υλοποιούνται σε ξεχωριστότµήµα λογισµικού (τον πηγαίο κώδικα του οποίου µπορεί να µην γνωρίζουµε) και να µεταφραστείεπιτυχώς. 14

Σύνδεση Όταν ένα πρόγραµµα µεταφράζεται µε βάση τις δηλώσεις που περιέχει ένα header file, ο κώδικας που παράγεται από τον µεταφραστή περιέχει αναφορές σε εξωτερικές µεταβλητές και συναρτήσεις. Για να παραχθεί ο τελικός εκτελέσιµος κώδικας, απαιτείται µια επιπλέον διαδικασία ενσωµάτωσηςτων ορισµών και υλοποιήσεων τους, που βρίσκονται σε κάποιο άλλο αρχείο που έχει ήδη µεταφραστεί. Αυτή η διαδικασία ονοµάζεται σύνδεση (linking). Αφού ο µεταφρασµένος κώδικας συνδεθεί µε όλα τα υπόλοιπα µεταφρασµένα τµήµατα που παρέχουν τους ορισµούς / υλοποιούν των εξωτερικών µεταβλητών / συναρτήσεων, δηµιουργείται το τελικό εκτελέσιµο. 15

/* foo.h */ extern int i; extern void boo(); 16 υλοποιείται από χρησιµοποιείται από /* foo.c */ /* main.c */ #include "foo.h" int i=0; #include "foo.h" int main(int argc, char *argv[]) { void boo() { i++; boo(); i++; boo();

/* foo.h */ extern int i; extern void boo(); /* foo.c */ #include "foo.h" int i=0; void boo() { i++; /* foo.c */ #include /* foo.h foo.h */ extern int i; extern void boo(); int i=0; void boo() { i++; /* foo.o */ ------------ 17 i -> 0 boo -> 5 ------------ 0 1 2 3 4 5 6 7 8 > gcc foo.c c o foo.o >

/* foo.h */ /* main.c */ extern int i; #include "foo.h" extern void boo(); /* foo.h */ /* main.c */ #include "foo.h" int main( ) { boo(); i++; boo(); extern int i; extern void boo(); int main( ) { boo(); i++; boo(); 18 /* main.o */ ------------ i ->??? boo ->??? ------------ 0 boo 1 i 2 3 i 4 boo > gcc main.c c o main.o >

/* main.o */ ------------ i ->??? boo ->??? ------------ 0 boo 1 i 2 + 3 i 4 boo /* foo.o */ ------------ i -> 0 boo -> 5 ------------ 0 1 2 3 4 5 6 7 8 /* test */ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 19 > gcc main.o foo.o o test >

Περισσότερα για το extern Ο προσδιορισµός externχρησιµοποιείται για τις δηλώσεις εξωτερικώνµεταβλητών / συναρτήσεων, που ορίζονται / υλοποιούνται σε ένα άλλο αρχείο. Η παράλειψη του externσε δήλωση συνάρτησης (που δεν υλοποιείται τοπικά) οδηγεί σε αναζήτηση για «ταιριαστή»υλοποίηση της συνάρτησης στα αρχεία µε τα οποία γίνεται σύνδεση του κώδικα. Η παράλειψη του externσε δήλωση (καθολικής) µεταβλητής δεν εγγυάται τοπικότητα Aν µια άλλη καθολική µεταβλητή δηλώνεται σε άλλο αρχείο µε το ίδιο όνοµα, κατά την διασύνδεση οι αναφορές σε αυτό το όνοµα θα αφορούν την ίδιαθέση µνήµης. 20

/* a.c */ int i; void incval() { i++; > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 16 > /* b.c */ extern void incval(); int main(int argc, char *argv[]) { extern int i; i=15; incval(); 21

/* a.c */ int i; void incval() { i++; > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 15 > /* b.c */ extern void incval(); int main(int argc, char *argv[]) { int i; i=15; incval(); 22

/* a.c */ int i; void incval() { i++; /* b.c */ extern int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 23 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 16 >

/* a.c */ extern int i; void incval() { i++; /* b.c */ int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 24 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 16 >

/* a.c */ extern int i; void incval() { i++; /* b.c */ extern int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 25 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test undefined reference to i >

26 όµως...

/* a.c */ int i; void incval() { i++; /* b.c */ int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 27 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test 15 16 >

/* a.c */ int i; void incval() { i++; /* b.c */ int i; void incval(); int main(int argc, char *argv[]) { i=15; incval(); 28 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test 15 16 >

/* a.c */ int i; void incval() { i++; /* b.c */ int i; int main(int argc, char *argv[]) { i=15; incval(); 29 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test >./test 15 16 >

Περισσότερα για το static Πως αποφεύγουµε µια καθολική µεταβλητή ή/και συνάρτηση που υλοποιούµε αποκλειστικά για τους σκοπούς του τοπικού κώδικασε ένα αρχείο να «προσπελασθεί» (κατά λάθος) µέσα από κώδικα που βρίσκεται σε άλλο αρχείο; Με τον προσδιορισµό staticεπιτυγχάνεται η επιθυµητή τοπικότητα, δηλαδή η εµβέλεια των καθολικών µεταβλητών / συναρτήσεων περιορίζεται στο αρχείο όπου αυτές δηλώνονται / υλοποιούνται. Είναι αδύνατο να γίνει αναφορά σε αυτές (είτε επίτηδες είτε κατά λάθος) µέσα από κώδικα που βρίσκεται σε ένα άλλο αρχείο. 30

/* a.c */ int i; void incval() { i++; /* b.c */ static int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 31 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 15 >

/* a.c */ static int i; void incval() { i++; /* b.c */ int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 32 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test > >./test 15 15 >

/* a.c */ static int i; void incval() { i++; /* b.c */ extern int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 33 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test undefined reference to i >

/* a.c */ int i; static void incval() { i++; /* b.c */ extern int i; extern void incval(); int main(int argc, char *argv[]) { i=15; incval(); 34 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test undefined reference to incval >

/* a.c */ int i; static void incval() { i++; /* b.c */ extern int i; int main(int argc, char *argv[]) { i=15; incval(); 35 > gcc a.c c o a.o > gcc b.c c o b.o > gcc a.o b.o o test undefined reference to incval >

Ένα «µικρό» πρόβληµα Όταν ένας κώδικας Α ορίζει µεταβλητές και υλοποιεί συναρτήσεις µε σκοπό αυτές να χρησιµοποιηθούν µέσα από οποιοδήποτε άλλο κώδικα, τότε αυτές δεν µπορεί να δηλωθούν ως static. Όταν ο κώδικας Α συνδεθεί µε ένα άλλο κώδικα Β, οι µεταβλητές / συναρτήσεις του Α είναι διαθέσιµες για σύνδεση µε αντίστοιχες (άµεσες ή έµµεσες) ) εξωτερικές δηλώσεις που υπάρχουν στον Β. Αν οι εξωτερικές δηλώσεις του Β έχουν προκύψει από λάθος (π.χ. παράλειψη προσδιορισµού staticσε δήλωση καθολικής µεταβλητής / συνάρτησης ή παράλειψη δήλωσης και υλοποίησης συνάρτησης), η διασύνδεση θα οδηγήσει σε λάθος αποτέλεσµα. 36

Η ρίζα του προβλήµατος Αναφορά σε εξωτερικές µεταβλητές / συναρτήσεις γίνεται µε βάση έναν επίπεδοχώρο ονοµάτων, όπου δεν µπορεί να αποκλεισθεί η τυχαίαχρήση του ίδιου ονόµατος από διαφορετικά τµήµατα κώδικα. Ο προγραµµατιστής δεν έχει τη δυνατότητα να προσδιορίσει το τµήµα λογισµικούτο οποίο θα πρέπει να παρέχει τον ορισµό / υλοποίηση µιας εξωτερικής µεταβλητής / συνάρτησης. Άλλες γλώσσες λύνουν το πρόβληµα δίνοντας σε κάθε τµήµα λογισµικού ένα µοναδικό όνοµαµε βάση το οποίο άλλα τµήµατα κώδικα µπορεί να αναφέρονται (χωρίς πιθανότητα λάθους) σε µεταβλητές και συναρτήσεις που αυτό προσφέρει. 37

Βιβλιοθήκες Τµήµατα λογισµικού γενικής χρησιµότητας, που έχουν σχεδιαστεί µε σκοπό να διευκολύνει την ανάπτυξη διαφορετικών εφαρµογών. Αναπτύσσονται όπως ένα (συµβατικό) ανεξάρτητο τµήµα λογισµικού, Με ξεχωριστή µετάφραση και (εκ των υστέρων) σύνδεση µε τον κώδικα των προγραµµάτων που τις χρησιµοποιούν. Οι βιβλιοθήκες χρησιµοποιούνται από τους προγραµµατιστές χωρίςγνώση για την εσωτερική υλοποίηση τους (black box). Τεκµηριώνονται µέσα από αναλυτικές περιγραφές χρήσης της προγραµµατιστικής διεπαφής τους βλέπε εγχειρίδια & βιβλία προγραµµατισµού. 38

Αφηρηµένος Τύπος εδοµένων (ΑΤ ) 39 Είναι η υλοποίηση νέας λειτουργικότητας στην µορφή ενός νέου τύπου δεδοµένων (συνήθως ως ένα black box). Είναι ένα τµήµα λογισµικού που φτιάχνεται ξεχωριστά, και µπορεί να χρησιµοποιηθεί µέσω µιας (τεκµηριωµένης) διεπαφής.

Παράδειγµα: Πολύ µεγάλοι ακέραιοι Λειτουργικότητα για ακεραίους αλλά για πολύ µεγάλεςτιµές, που υπερβαίνουν (κατά πολύ) τα όρια των µεγάλων ακεραίων του επεξεργαστή µας. Μπορούµε να εισάγουµε ένα νέο τύπο δεδοµένων VeryBigInt ως ΑΤ,, π.χ... µε πράξεις για την: : αρχικοποίηση µεταβλητών πρόσθεση και αφαίρεση µεταβλητών κλπ Ο προγραµµατιστής χρησιµοποιεί την παραπάνω λειτουργικότητα χωρίς να νοιάζεται για το πως αυτή υλοποιείται «εσωτερικά» στον ΑΤ. 40

διεπαφή για τον τύπο VeryBigInt typedef VeryBigInt; void vbi_set(verybigint *i, char *s); char *vbi_get(verybigint *i); 41 int vbi_add(verybigint *i1, const VeryBigInt *i2); int vbi_diff(verybigint *i1, const VeryBigInt *i2); vbi_set vbi_get vbi_add vbi_diff αντικείµενο VeryBigInt ως black box

/* ενδεικτική διεπαφή για ΑΤ VeryBigInt */ typedef VeryBigInt; int vbi_set(verybigint *i, char *s); /* αρχικοποιεί την µεταβλητή µε βάση την ακέραια τιµή που περνιέται ως αλφαριθµητικό, και επιστρέφει 1 / 0 για επιτυχία / αποτυχία */ 42 char *vbi_get(verybigint *i); /* επιστρέφει την τιµή ως αλφαριθµητικό, η µνήµη του οποίου πρέπει να αποδεσµευτεί από τον καλών κώδικα */ int vbi_add(verybigint *i1, const VeryBigInt *i2); /* i1 = i1 + i2 και επιστρέφει 1 για επιτυχία ή 0 αν ξεπεραστεί το υποστηριζόµενο πεδίο τιµών */ int vbi_diff(verybigint *i1, const VeryBigInt *i2); /* i1 = i1 - i2 και επιστρέφει 1 για επιτυχία ή 0 αν ξεπεραστεί το υποστηριζόµενο πεδίο τιµών */

int main(int argc, char *argv[]) { int res; VeryBigInt i1,i2; char s[512],*s2; scanf("%511s,s); res=vbi_set(&i1,s); if (!res) { printf("set error for %s\n",s); return; 43 scanf("%511s,s); res=vbi_set(&i2,s); if (!res) { printf("set error for %s\n",s); return; res=vbi_add(&i1,&i2); if (!res) { printf("range error\n"); return; s2=vbi_get(&i1); printf("%s\n",s2); free(s2);

Ενδεικτική Υλοποίηση Κάθε µεταβλητή αντιστοιχεί σε ένα πίνακα από χαρακτήρες, στον οποίο αποθηκεύονται τα δεκαδικά ψηφία της τρέχουσας τιµής ως απλοί χαρακτήρες. Το πρόσηµο της τιµής αποθηκεύεται στον πίνακα. Η vbi_set αρχικοποιεί τον πίνακα µε βάση το αλφαριθµητικό που περνιέται σαν παράµετρος. Η vbi_getδεσµεύει ένα πίνακα χαρακτήρων στη δυναµική µνήµη και αποθηκεύει την τιµή ως κανονικό (εκτυπώσιµο) αλφαριθµητικό (µε τερµατικό). Οι vbi_addκαι vbi_diffυλοποιούν τις πράξεις µε συµβολικό τρόπο ψηφίο προς ψηφίο.. 44

VeryBigInt i; vbi_set(&i,"-1234"); 45 0 N-1 '-' '0' '0' '1' '2' '3' '4' '5'

Παράδειγµα: Τύπος Date Λειτουργικότητα για τη διαχείριση ηµεροµηνιών. ΑΤ Date, π.χ. µε πράξεις για την: ανάθεση τιµής σε µεταβλητή εξαγωγή τιµής από µεταβλητή αύξηση µεταβλητής κατά ένα (µια µέρα) σύγκριση των τιµών δύο µεταβλητών Θέλουµε ο προγραµµατιστής να χρησιµοποιεί την παραπάνω λειτουργικότητα χωρίς να νοιάζεται για το πως αυτή υλοποιείται «εσωτερικά» στον ΑΤ. 46

διεπαφή για τον τύπο Date typedef Date; int date_set(date *dt, int d, int m, int y); void date_get(date *dt, int *d, int *m, int *y); void date_inc(date *dt); int date_diff(date *dt1, Date *dt2); 47 date_set date_get date_inc αντικείµενο Date ως black box date_diff

#define OK 0 #define ILLEGAL_DAY_VALUE -1 #define ILLEGAL_MONTH_VALUE -2 #define ILLEGAL_YEAR_VALUE -3 typedef struct { int day,month,year; Date; 48 int date_set(date *dt, int d, int m, int y); /* αρχικοποιεί την µεταβλητή µε τις τιµές που δίνονται σαν παράµετροι, και επιστρέφει 0 για επιτυχία, διαφορετικά τιµή < 0 */ void date_get(const Date *dt, int *d, int *m, int *y); /* αποθηκεύει την τιµή της µεταβλητής στις µεταβλητές που δίνονται σαν παράµετροι */ void date_inc(date *dt); /* προχωρά την τιµή της µεταβλητής κατά 1 µέρα */ int date_diff(const Date *dt1, const Date *dt2); /* επιστρέφει τη διαφορά της ηµεροµηνίας dt2 από την ηµεροµηνία dt1, σε αριθµό των ηµερών */

ηµιουργία Στατικής Βιβλιοθήκης ηµιουργία της προγραµµατιστικής διεπαφής και του αντίστοιχου header file. Υλοποίηση της λειτουργικότητας (σε ένα ή περισσότερα αρχεία κώδικα.c) Μεταγλώττιση κάθε αρχείου κώδικα και δηµιουργία ενός αντίστοιχου object file (.ο) gcc -Wall -c <code_filename> -o <object_filename> ηµιουργία βιβλιοθήκης ar rcs <library_filename> <object_filenames> Το όνοµα της βιβλιοθήκης πρέπει να αρχίζει από lib ενώ η κατάληξη του αρχείου πρέπει να είναι.a Π.χ. ar rcs libmy_lib.a my_lib.o 49

Χρήση Στατικής Βιβλιοθήκες Συµπερίληψη (#include) του header file της βιβλιοθήκης Χρήση στον κώδικά µας των συναρτήσεων που παρέχει η βιβλιοθήκη (όπως τεκµηριώνονται στις οδηγίες χρήσης και το header file) Μεταγλώττιση & σύνδεση: gcc......... -l<όνοµα βιβλιοθήκης> - L<τοποθεσία_βιβλιοθήκης> Από το όνοµα βιβλιοθήκης αφαιρούµε το lib και το.a Π.χ. gcc my_code.c -o my_code -lmy_lib -L. 50