H ΓΛΩΣΣΑ C. Μάθηµα 8: είκτες. ηµήτρης Ψούνης

Σχετικά έγγραφα
H ΓΛΩΣΣΑ C. Μάθηµα 7: Πίνακες. ηµήτρης Ψούνης

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

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

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

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

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

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

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

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

H ΓΛΩΣΣΑ C. Μάθηµα 12: υναµική έσµευση Μνήµης. ηµήτρης Ψούνης

Εισαγωγή στον Προγραµµατισµό «C»

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

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

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

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

scanf() scanf() stdin scanf() printf() int float double %lf float

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

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

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

ΑΣΚΗΣΗ 6: ΔΕΙΚΤΕΣ. Σκοπός της Άσκησης. 1. Εισαγωγικά στοιχεία για τους Δείκτες

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

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

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

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

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

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

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

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

H ΓΛΩΣΣΑ C. Μάθηµα 4: Τελεστές και η οµή Ελέγχου (if$else) ηµήτρης Ψούνης

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

ΗΥ-150. Πίνακες (Arrays)

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

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

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

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

H ΓΛΩΣΣΑ C. Μάθηµα 17: Είσοδος/Έξοδος: Επικοινωνία µε το Λειτουργικό Σύστηµα. ηµήτρης Ψούνης

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

Διάλεξη 11η: Δείκτες, μέρος 1

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

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

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

H ΓΛΩΣΣΑ C. Μάθηµα 15: Είσοδος/Έξοδος: Συναρτήσεις Εισόδου. ηµήτρης Ψούνης

ΑΣΚΗΣΗ 5: ΠΙΝΑΚΕΣ. Σχήµα 1: H έννοια των πινάκων

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

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

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

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

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

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

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

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

Ορισμός μεταβλητών δεικτών και αρχικοποίηση

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

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

Κεφάλαιο Πίνακες Ι. (Διάλεξη 16)

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

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

ΣΥΝΑΡΤΗΣΕΙΣ (Functions)

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

ΗΥ-150. Προγραµµατισµός. Πίνακες (Arrays)

6. ΠΙΝΑΚΕΣ & ΑΛΦΑΡΙΘΜΗΤΙΚΑ

Κεφάλαιο 8.7. Πολυδιάστατοι Πίνακες (Διάλεξη 19)

ΥΠΟΛΟΓΙΣΤΕΣ ΙΙ. Τι περιλαμβάνει μια μεταβλητή; ΔΕΙΚΤΕΣ. Διεύθυνση μεταβλητής. Δείκτης

Προγραµµατιστικές τεχνικές

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

Διάλεξη 5: Δείκτες και Συναρτήσεις

οµές (structures) και Eνώσεις (unions)

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

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

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

Συναρτήσεις. Κατασκευαστικά Τεµάχια για τη ηµιουργία Αρθρωτών Προγραµµάτων

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

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

3 Αναδροµή και Επαγωγή

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

C Programming EPL032 Maria Stavrinou Ioannou Εισαγωγή στη Γλώσσα C

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

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

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

ΕΡΓΑΣΤΗΡΙΟ 11 - Απαντήσεις

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

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

2.2.3 Η εντολή Εκτύπωσε

Εισαγωγή στις Συναρτήσεις

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

Διδάσκων: Παναγιώτης Ανδρέου

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

Κεφάλαιο 5ο: Εντολές Επανάληψης

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

for for for for( . */

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

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Αναφορές

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

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

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

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

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Αναφορές-Παράμετροι

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

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

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

Transcript:

H ΓΛΩΣΣΑ C Μάθηµα 8: είκτες ηµήτρης Ψούνης

. Παρατηρήσεις 1. ιοχέτευση πίνακα ως όρισµα σε συνάρτηση 2. Η Σταθερά NULL Ασκήσεις 2 Περιεχόµενα Μαθήµατος Α. είκτες 1. Η µνήµη του υπολογιστή 2. Η έννοια του δείκτη 3. Ορισµός είκτη 4. Απόδοση τιµής σε δείκτη (Ο τελεστής &) 5. Απόδοση τιµής µέσω δείκτη (ο τελεστής *) 6. Παράδειγµα χρήσης δείκτη Β. είκτες και Πίνακες 1. Το όνοµα ενός πίνακα είναι δείκτης 2. Αποθήκευση ενός πίνακα στη µνήµη 3. Αριθµητική εικτών 4. Ισοδύναµος Συµβολισµός για πρόσβασή σε πίνακα Γ. είκτες και Συναρτήσεις 1. ιοχέτευση είκτη σε Συνάρτηση 2. ιοχέτευση Ορίσµατος σε Συνάρτηση µέσω Τιµής 3. ιοχέτευση Ορίσµατος σε Συνάρτηση µέσω Αναφοράς

3 A. είκτες 1. Η Μνήµη του Υπολογιστή Έχουµε ήδη δει κάποιες πληροφορίες για την οργάνωση της µνήµης σε ένα πρόγραµµα. Σε µια απλουστευµένη (αλλά επαρκή) προσέγγιση µπορούµε να φανταστούµε την µνήµη σαν µια ταινία µε χώρους αποθήκευσης δεδοµένων. Κάθε χώρος αποθήκευσης είναι 1 byte (δηλαδή 8 bits). Προκειµένου να µπορούµε να εντοπίσουµε κάθε χώρο αποθήκευσης, έχει έναν αναγνωριστικό αύξων αριθµό (που λέγεται διεύθυνση µνήµης). Έτσι η εικόνα που πρέπει να έχουµε για την µνήµη θα είναι κελιά, το κάθε ένα µε έναν αναγνωριστικό αριθµό, το οποίο θα έχει µέγεθος 1 byte: 0 1Byte 1 2 1000 1001 10000 10001 2x10 9 1Byte 1Byte 1Byte 1Byte 1Byte 1Byte 1Byte

4 A. είκτες 1. Η Μνήµη του Υπολογιστή Είδαµε ότι µια συνάρτηση έχει τον δικό της χώρο αποθήκευσης µεταβλητών. Όταν πρόκειται να εκτελεστεί µια συνάρτηση, δεσµεύεται ο χώρος της µνήµης για τις µεταβλητές της συνάρτησης. Έτσι αν για παράδειγµα η main καλεί µια συνάρτηση που έχουµε γράψει (έστω µε όνοµα f), τότε ο µεταγλωττιστής θα µεριµνήσει ώστε κάθε συνάρτηση να έχει τον χώρο της στην µνήµη. Ο χώρος που δεσµεύεται είναι αρκετά µεγάλος για να χωρέσει πάρα πολλές µεταβλητές (το ακριβές πλήθος καθορίζεται από το λειτουργικό σύστηµα, το µεταγλωττιστή κ.λπ.) Χώρος της f Χώρος της main 1000 1001 1002 15448 15449

5 A. είκτες 1. Η Μνήµη του Υπολογιστή Όταν δηλώνουµε µεταβλητές σε µια συνάρτηση, ο µεταγλωττιστής επιλέγει κάποιον από τον ελεύθερο χώρο της συνάρτησης για να αποθηκεύσει την µεταβλητή. Έτσι αν π.χ. η f δηλώνει στον χώρο δήλωσης µεταβλητών της δύο ακέραιες µεταβλητές, έστω την x και την y (θεωρούµε ότι µια ακέραια µεταβλητή δεσµεύει 4 bytes όπως συζητήσαµε σε προηγούµενο µάθηµα) Τότε η εικόνα της µνήµης θα είναι η εξής x y 1014 1015 1016 1017 1057 1058 1059 1060 Χώρος της f Χώρος της main

6 A. είκτες 1. Η Μνήµη του Υπολογιστή Έτσι αν γράψουµε x=1 και y=5 µε εντολές καταχώρησης στο σώµα της f, τότε αποθηκεύονται στις µεταβλητές οι αντίστοιχες τιµές. Ο τρόπος αποθήκευσης στο δυαδικό σύστηµα των αριθµών αυτών δεν µας ενδιαφέρει όταν γράφουµε το πρόγραµµά µας. x y 1014 1015 1016 1017 1057 1058 1059 1060 1 5 Χώρος της f Χώρος της main Συνοψίζοντας αντιλαµβανόµαστε ότι µία µεταβλητή µπορεί να εντοπιστεί πλήρως από δύο δεδοµένα: τον τύπο δεδοµένων της (για να ξέρουµε πόσα bytes δεσµεύει στην µνήµη) και το πρώτο byte στο οποίο είναι αποθηκευµένη. Π.χ. Για την x αν ξέρω ότι είναι ακέραια και το 1 ο byte της είναι το 1014, τότε µπορώ να εξάγω ότι θα είναι αποθηκευµένη στα bytes 1014-1017.

7 A. είκτες 2. Η Έννοια του είκτη Έτσι λοιπόν, η εικόνα που θα πρέπει να έχουµε στο µυαλό µας, είναι ότι κάθε µεταβλητή έχει έναν χώρο αποθήκευσης (ίσου µε το µέγεθος της µεταβλητής σε bytes) µε αναγνωριστικό τη διεύθυνση µνήµης του 1 ου byte που αυτή δεσµεύει. x y 1014 1057 1 5 Χώρος της f Χώρος της main Από την στιγµή όµως που η διεύθυνση µνήµης είναι ένας αριθµός, µπορεί να αντιµετωπιστεί σαν οποιοσδήποτε άλλος αριθµός στην C. Άρα για παράδειγµα µπορούµε να δηλώσουµε µια µεταβλητή στην οποία να αποθηκεύουµε την διεύθυνση µνήµης µιας άλλης µεταβλητής!

8 A. είκτες 2. Η Έννοια του είκτη Συνεπώς µπορούµε να δηλώσουµε µια µεταβλητή (έστω µε όνοµα ptr) που θα αποθηκεύσουµε π.χ. την διεύθυνση της µεταβλητής x. Αυτή η µεταβλητή, η οποία αποθηκεύει ως τιµή την διεύθυνση µνήµης άλλων µεταβλητών ονοµάζεται δείκτης: Χώρος της f Μεταβλητή x είκτης ptr 1014 1057 1 1014 Χώρος της main είτε λοιπόν ότι ο δείκτης ptr έχει ως τιµή την διεύθυνση της µεταβλητής x. Θα λέµε για το λόγο αυτό, ότι ο δείκτης ptr δείχνει στην µεταβλητή x

9 A. είκτες 3. Ορισµός είκτη Ένας δείκτης δηλώνεται µε την εντολή δήλωσης: Τύπος_ εδοµένων *Ονοµα_ είκτη ηλώνουµε έναν δείκτη µε όνοµα «Ονοµα_ είκτη» που θα δείχνει σε µια µεταβλητή τύπου δεδοµένων «Τύπος_ εδοµένων» Παραδείγµατα: int *p; Εδώ δηλώνουµε έναν δείκτη σε ακέραιο µε όνοµα p. double *ptr; Εδώ δηλώνουµε έναν δείκτη σε double µε όνοµα ptr ιαπιστώστε ότι ένας δείκτης είναι ακόµη ένας τύπος δεδοµένων. Με την ιδιαιτερότητα ότι οι µεταβλητές που θα αποθηκεύει θα είναι διευθύνσεις µνήµης. Ο τύπος δεδοµένων συµβολικά είναι (int *) και (double *) αντίστοιχα στις δηλώσεις που είδαµε.

10 A. είκτες 4. Απόδοση Τιµής σε είκτη Για να έχει νόηµα ένας δείκτης πρέπει να τον συσχετίσουµε µε µια µεταβλητή, ή όπως λέµε να τον βάλουµε να δείχνει στην µεταβλητή. Αυτό γίνεται µε τον εξής τρόπο: int x; int *p; p=&x; // Βάλε τον δείκτη p να δείχνει στην x. Ο τελεστής & (θα τον διαβάζουµε «διεύθυνση του») µπαίνει µπροστά από µια µεταβλητή και µας επιστρέφει την διεύθυνση του. Άρα: αν η x είναι αποθηκευµένη π.χ. στην διεύθυνση 10333, τότε η τιµή &x (διεύθυνση του x) είναι 10333, άρα η τιµή της p µετά την εντολή ανάθεσης είναι 10333.

11 A. είκτες 5. Απόδοση Τιµής µέσω είκτη (Ο τελεστής *) Ο τελεστής * (που ονοµάζεται τελεστής έµµεσης διευθυνσιοδότησης) έχει δύο χρήσεις: Είδαµε την πρώτη που είναι να δηλώσουµε µια µεταβλητή τύπου δείκτη. Η δεύτερη χρήση είναι η εξής: Αν σε µία εντολή, βάλουµε το * µπροστά από έναν δείκτη, τότε αναφερόµαστε στην µεταβλητή που δείχνει ο δείκτης. Βλέπουµε το παράδειγµα: int x; int *p; p=&x; *p=5; //Η µεταβλητή που δείχνει το *p (άρα το x) παίρνει την τιµή 5 Μετά από αυτό το παράδειγµα αντιλαµβανόµαστε ότι έχουµε δύο τρόπους για να έχουµε πρόσβαση στην µεταβλητή x: Απευθείας µε το όνοµα της x (άµεση πρόσβαση) Μέσω του δείκτη που δείχνει στην x (έµµεση πρόσβαση)

12 A. είκτες 6. Παράδειγµα Χρήσης εικτών Μεταγλωττίστε, εκτελέστε και µελετήστε το πρόγραµµα: /* pointers.c: Deixnei tin vasiki xrisi twn deiktwn */ #include <stdio.h> main() { int x; int *ptr; ptr=&x; } x=5; printf("x=%d\t *ptr=%d\t &x=%d\t ptr=%d",x,*ptr,&x,ptr); *ptr=8; printf("\nx=%d\t *ptr=%d\t &x=%d\t ptr=%d",x,*ptr,&x,ptr); x=9; printf("\nx=%d\t *ptr=%d\t &x=%d\t ptr=%d",x,*ptr,&x,ptr);

13 Β. είκτες και Πίνακες 1. Το Όνοµα ενός Πίνακα είναι είκτης Οι δείκτες είναι πολύ χρήσιµοι σε συνδυασµό µε τους πίνακες! Αυτό συµβαίνει διότι εξ ορισµού το όνοµα κάθε πίνακα είναι ένας δείκτης µε τύπο δεδοµένων τον τύπο δεδοµένων του πίνακα. Ωστόσο είναι ένας δείκτης που δεν µπορούµε να αλλάξουµε την τιµή του. Μπορούµε όµως να ορίσουµε έναν δείκτη να δείχνει στην αρχή του πίνακα µε τον εξής τρόπο: int pinakas[100]; int *ptr; ptr=pinakas; Ο δείκτης θα δείχνει στον πρώτο ακέραιο αριθµό του πίνακα. Ο δείκτης ptr µπορεί να αλλάξει! Σηµειώστε εδώ ότι θα µπορούσαµε να βάλουµε τον δείκτη να δείχνει στο πρώτο στοιχείο του πίνακα και µε την εντολή int pinakas[100]; int *ptr; ptr=&pinakas[0]; Ωστόσο είναι σηµαντικό να γνωρίζουµε τον πρώτο τρόπο. ptr=&pinakas[0]

14 Β. είκτες και Πίνακες 2. Αποθήκευση ενός Πίνακα στη Μνήµη Στο µάθηµα 8, είδαµε ότι τα στοιχεία ενός πίνακα αποθηκεύονται σε διαδοχικές θέσεις µνήµης. Έφτασε η ώρα να το διαπιστώσουµε και πειραµατικά. Είδαµε ότι µε την δήλωση: int pin[4]; ηµιουργείται ένας πίνακας 4 διαδοχικών θέσεων στην µνήµη Χώρος της συνάρτησης pin[0] pin[1] pin[2] pin[3] Γνωρίζουµε πλέον ότι &pin[0],&pin[1],&pin[2],&pin[3] είναι οι διευθύνσεις µνήµης των 4 µεταβλητών του πίνακα. Το πρόγραµµα της επόµενης διαφάνειας δείχνει ότι όντως οι µεταβλητές αυτές αποθηκεύονται σε διαδοχικές θέσεις µνήµης.

15 Β. είκτες και Πίνακες 2. Αποθήκευση ενός Πίνακα στη Μνήµη Μεταγλωττίστε, εκτελέστε και µελετήστε το πρόγραµµα: /* matrix_pointers.c: Deixnei oti oi theseis mnimis enos pinaka einai diadoxikes */ #include <stdio.h> #define N 4 main() { int pin[n]; int i; } for (i=0; i<n; i++) printf("\nstoixeio:%d, Diefthinsi Thesis Mnimis: %d",i, &pin[i]);

16 Β. είκτες και Πίνακες 3. Αριθµητική εικτών Μεγάλη προσοχή. Οι δείκτες έχουν µια ιδιαίτερη αριθµητική έτσι ώστε να δουλεύουν αποδοτικά σε συνδυασµό µε τους πίνακες: Έστω το πρόγραµµα int pinakas[100]; int *ptr; ptr=pinakas; Η εντολή: ptr++; εν αυξάνει την τιµή του δείκτη κατά 1! Αλλά αυξάνει την τιµή του δείκτη κατά τόσα bytes όσα είναι και ο τύπος δεδοµένων του δείκτη (για ακέραιο: κατά 4!). Ενώ η εντολή: ptr--; Μειώνει την τιµή του δείκτη κατά τόσα bytes όσα είναι και ο τύπος δεδοµένων του δείκτη (για ακέραιο: κατά 4!).

17 Β. είκτες και Πίνακες 3. Αριθµητική εικτών Το παρακάτω πρόγραµµα δείχνει πως µπορούµε να διατρέξουµε τα στοιχεία ενός πίνακα µέσω ενός βοηθητικού δείκτη και όχι απ ευθείας! /* pointer_calc.c: Pws exoume prosvasi sta stoixeia enos pinaka mesw deikti */ #include <stdio.h> #define N 10 main() { int pin[n]; int i; int *ptr; } ptr=pin; for (i=0; i<n; i++) { printf("\nstoixeio:%d, Diefthinsi Thesis Mnimis: %d",i, ptr); ptr++; }

18 Β. είκτες και Πίνακες 3. Αριθµητική εικτών Για την ώρα µπορεί να µην φαίνεται χρήσιµο, γιατί να κάνουµε πρόσβαση στα στοιχεία του πίνακα µε αυτόν τον τρόπο! Αργότερα όµως θα δούµε πραγµατικά χρήσιµες εφαρµογές αυτής της ιδιότητας. Ας δούµε όµως ένα ακόµη παράδειγµα: double pinakas[100]; double *ptr; ptr=pinakas; ptr+=2; Η εντολή ptr+=2 λοιπόν θα αυξήσει την τιµή της ptr κατα 2 x (το µέγεθος του double), άρα θα αυξήσει τη διεύθυνση κατά 16, αφού µία double µεταβλητή δεσµεύει 8 bytes. Μετά το πέρας της εκτέλεσης αυτών των εντολών ο δείκτης ptr θα δείχνει στο στοιχείο pinakas[2].

19 Β. είκτες και Πίνακες 4. Ισοδύναµος Συµβολισµός για την Πρόσβαση σε Πίνακα Με βάση την αριθµητική δεικτών, η παράσταση: *(array+2) Μπορεί να εξηγηθεί ως εξής: Το (array+2) δίνει την διεύθυνση του 3 ου στοιχείου του πίνακα. Άρα µε το * µπροστά, µας δίνει την τιµή του 3 ου στοιχείου του πίνακα. Έτσι για παράδειγµα ο βρόχος: for (i=0; i<n; i++) printf("%d",array[i]); µπορεί να γραφεί ισοδύναµα: for (i=0; i<n; i++) printf("%d",*(array+i));

20 Γ. είκτες και Συναρτήσεις 1. ιοχέτευση είκτη σε Συνάρτηση Από τη στιγµή που ένας δείκτης µπορεί να ειδωθεί σαν µια µεταβλητή (στην οποία αποθηκεύονται διευθύνσεις µεταβλητών), έχουµε κάθε δικαίωµα να τον περάσουµε ως όρισµα σε µια συνάρτηση. Π.χ. Το ακόλουθο πρωτότυπο συνάρτησης: int func(int *p, int x) έχεται ως ορίσµατα δύο πράγµατα: Έναν δείκτη σε ακέραιο (το p) και έναν ακέραιο (το x) Μπορεί βεβαίως και από µία συνάρτηση να επιστραφεί ένας δείκτης σε µια µεταβλητή. Το πρωτότυπο µιας τέτοιας συνάρτησης θα είναι: int *func2(float y) Όπου στο σώµα της συνάρτησης θα ορίζουµε ότι επιστρέφεται ένας δείκτης σε ακέραια µεταβλητή. Μας ενδιαφέρει αυτό; ΠΑΡΑ ΠΟΛΥ! Το πως περνάµε µια µεταβλητή (µέσω µεταβλητής ή µέσω δείκτη) είναι από τις πιο σηµαντικές προγραµµατιστικές τεχνικές της C!

21 Γ. είκτες και Συναρτήσεις 2. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Τιµής Στο µάθηµα 6 «Συναρτήσεις», είδαµε ότι κάθε συνάρτηση έχει τον δικό της χώρο µεταβλητών στην µνήµη. Ας µελετήσουµε για να θυµηθούµε τις ιδιότητες αυτές ένα απλό πρόγραµµα. /*byvalue.c: Perasma orismatwn mesw timis */ #include <stdio.h> void swap(int a,int b); main() { int a=5,b=10; printf("\nmain: a=%d,b=%d",a,b); swap(a,b); printf("\nmain: a=%d,b=%d",a,b); } void swap(int a, int b) { int k; k=a; a=b; b=k; printf("\nswap: a=%d,b=%d",a,b); }

22 Γ. είκτες και Συναρτήσεις 2. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Τιµής Ας θυµηθούµε πως δουλεύει το πρόγραµµα αυτό. Πριν την κλήση της συνάρτησης swap, οι µεταβλητές a και b έχουν πάρει τις τιµές a=5 και b=10. Συνεπώς όταν γίνεται η κλήση της swap, τα ορίσµατα a, και b της συνάρτησης swap έχουν αντίστοιχα τιµές 5 και 10. Η εικόνα της µνήµης είναι: Χώρος της main a 5 Χώρος της swap b a b 10 5 10 Αφού εκτελεστούν οι εντολές της swap, αλλάζουν οι τιµές των a και b στην swap, αλλά επειδή αυτές είναι τοπικές µεταβλητές στην swap η τιµή των a,b στην main δεν αλλάζει! Η εικόνα της µνήµης είναι: Χώρος της main a 5 Χώρος της swap b a b 10 10 5

23 Γ. είκτες και Συναρτήσεις 2. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Τιµής Πρακτικά, όταν περνάµε ορίσµατα µέσω µεταβλητών, οι αλλαγές που γίνονται στις µεταβλητές που διοχετεύουµε ως ορίσµατα, δεν θα εξακολουθούν να υφίστανται όταν ο έλεγχος του προγράµµατος επιστρέψει στη καλούσα συνάρτηση. Αυτός ο τρόπος για να περάσουµε ένα όρισµα σε µια συνάρτηση λέγεται διοχέτευση ορίσµατος σε συνάρτηση µέσω τιµής (by value) υπό την έννοια ότι στην συνάρτηση έχουµε στα χέρια µας την τιµή της µεταβλητής και όχι την ίδια την µεταβλητή. Είναι προφανές ότι σε κάποιες συναρτήσεις θα επιθυµούµε να αλλάζει η τιµή της µεταβλητής µέσα στην συνάρτηση και αυτό να µπορεί να το «δει» και η καλούσα συνάρτηση. Αυτός είναι ο δεύτερος τρόπος για να περάσουµε ένα όρισµα σε µια συνάρτηση, λέγεται διοχέτευση ορίσµατος σε συνάρτηση µέσω αναφοράς (by reference) και όπως θα δούµε στην συνέχεια δεν διοχετεύουµε ως όρισµα την µεταβλητή, αλλά δείκτη στην µεταβλητή!

24 Γ. είκτες και Συναρτήσεις 3. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Αναφοράς Άρα τροποποιούµε την συνάρτηση µας ως εξής: /*byreference.c: Perasma orismatwn mesw anaforas */ #include <stdio.h> void swap(int *ptra, int *ptrb); main() { int a=5,b=10; printf("\nmain: a=%d,b=%d",a,b); swap(&a,&b); printf("\nmain: a=%d,b=%d",a,b); } void swap(int *ptra, int *ptrb) { int k; k=*ptra; *ptra=*ptrb; *ptrb=k; printf("\nswap: a=%d,b=%d",*ptra,*ptrb); }

25 Γ. είκτες και Συναρτήσεις 3. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Αναφοράς Να δούµε πως δουλεύει το πρόγραµµα αυτό. Πριν την κλήση της συνάρτησης swap, οι µεταβλητές a και b έχουν πάρει τις τιµές a=5 και b=10. Ας υποθέσουµε ότι η διεύθυνση της a είναι 1000 και της b 1012. Χώρος της main a 5 b 10 1000 1012 Χώρος της swap ptra ptrb Η τιµή &a, υπολογίζεται στο 1000, ενώ η τιµή &b υπολογίζεται στο 1012. Συνεπώς όταν αρχίζει η εκτέλεση της swap η εικόνα της µνήµης είναι: Χώρος της main a 5 b 10 1000 1012 Χώρος της swap ptra ptrb 1000 1012

Γ. είκτες και Συναρτήσεις 3. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Αναφοράς Ας δούµε τώρα αναλυτικά τις εντολές που τρέχουν στην swap: k=*ptra; //Αναθέτει στην µεταβλητή k την τιµή της µεταβήτης που δείχνει ο ptra Χώρος της main a 5 b 10 1000 1012 Χώρος της swap ptra ptrb 1000 1012 k 5 26 *ptra=*ptrb; Αναθέτει στην µεταβλητή που δείχνει ο ptra την τιµή που δείχνει ο ptrb Χώρος της main a 10 b 10 ptra 1000 Χώρος της swap ptrb 1012 k 5 1000 1012 *ptrb=k; Αναθέτει στην µεταβλητή που δείχνει ο ptrb την τιµή του k Χώρος της main a 10 b 5 1000 1012 Χώρος της swap ptra ptrb k 1000 1012 5

27 Γ. είκτες και Συναρτήσεις 3. ιοχέτευση Ορίσµατος σε Συνάρτηση Μέσω Αναφοράς Τι παρατηρούµε: Ότι µε έµµεσο τρόπο η συνάρτηση προσπελαύνει τις ίδιες τις µεταβλητές της main! Άρα για τον λόγο αυτό, οι αλλαγές που κάνουµε στις µεταβλητές παραµένουν και στην main! Συνοψίζοντας: Αν θέλουµε να αλλάξει η τιµή µια µεταβλητής σε µια συνάρτηση και το αποτέλεσµα αυτό να διατηρηθεί και στην καλούσα συνάρτηση, διοχετεύουµε το όρισµα µέσω αναφοράς (δηλαδή µέσω δείκτη) Αλλιώς διοχετεύουµε το όρισµα απλά µέσω τιµής. Επιπλέον: είτε ότι µε τον τρόπο αυτό µπορούµε να έχουµε περισσότερα από ένα επιστρεφόµενα αποτελέσµατα. Το ένα επιστρεφόµενο αποτέλεσµα θα το πάρουµε από την return και το άλλο µέσω δείκτη! Ή ακόµη πιο απλά µπορούµε να πάρουµε και τις δύο επιστρεφόµενες τιµές µέσω δείκτη.

28. Παρατηρήσεις 1. ιοχέτευση Πίνακα ως Όρισµα σε Συνάρτηση Σηµείωση: Επειδή είναι πολύ συνηθισµένο να διοχετεύουµε έναν πίνακα ως όρισµα, και για να είναι πιο εµφανές στην ανάγνωση ότι πρόκειται περί πίνακα και όχι δείκτη σε µεταβλητή, η C µας δίνει την δυνατότητα: Αντί να γράψουµε το πρωτότυπο: void print(int *pinakas, int n); Να γράψουµε το πρωτότυπο: void print(int pinakas[], int n); Οποιοδήποτε από τα δύο πρωτότυπα και να χρησιµοποιήσουµε θα έχουµε το ίδιο αποτέλεσµα. Με βάση τα παραπάνω εξ ορισµού το πέρασµα ενός πίνακα σε µία συνάρτηση γίνεται µέσω αναφοράς. Άρα θα θυµόµαστε ότι οποιαδήποτε αλλαγή γίνεται σε έναν πίνακα που διοχετεύουµε ως όρισµα, παραµένει και στην καλούσα συνάρτηση. Αν θέλουµε να περάσουµε αντίγραφο του πίνακα ως όρισµα σε µία συνάρτηση, θα πρέπει να κατασκευάσουµε πρώτα ένα αντίγραφό του.

29. Παρατηρήσεις 2. Η Σταθερά NULL Ένα πολύ συνηθισµένο λάθος είναι να καταχωρούµε τιµή σε έναν δείκτη που δεν τον έχουµε συσχετίσει µε µια µεταβλητή. Π.χ. ο κώδικας: int x; int *p; *p=15; Θα δηµιουργήσει σφάλµα εκτέλεσης! Το p δεν δείχνει πουθενά, άρα όταν πάµε να εκτελέσουµε την εντολή δεν επηρεάζουµε κάποια µεταβλητή, άρα το πρόγραµµα έχει µια απροσδόκητη συµπεριφορά! Συνεπώς πάντα όταν δηλώνουµε ένα δείκτη, θα πρέπει να τον συσχετίζουµε µε µια µεταβλητή η οποία θα είναι αποθηκευµένη στην µνήµη. Θα υπάρξουν και κάποιες περιπτώσεις που θα θέλουµε ο δείκτης να µην έχει τιµή. Για τον λόγο αυτό στην C είναι ορισµένη µία συµβολική σταθερά, το NULL, την οποία θα την χρησιµοποιούµε συµβολικά για να λέµε ότι «ο δείκτης δεν δείχνει πουθενά». Παράδειγµα: int *p; p=null; /* O p δεν δείχνει πουθενά */

30 Ε. Ασκήσεις 1. Υπολογισµός Ριζών Β Βάθµιας Εξίσωσης 1. Γράψτε µια συνάρτηση µε όνοµα: int rizes(float a, float b, float c, float *x1, float *x2); Η οποία να υπολογίζει τις ρίζες της εξίσωσης ax 2 +bx+c=0. Η συνάρτηση να επιστρέφει (µέσω ορίσµατος) στις µεταβλητές x1 και x2 τις πραγµατικές ρίζες της εξίσωσης και να επιστρέφει µε return το πλήθος των λύσεων της εξίσωσης Βοήθεια: Θα χρειαστείτε την συνάρτηση: double sqrt(double x); Η οποία είναι ορισµένη στο αρχείο κεφαλίδας math.h Βοήθεια: Ο προσδιοριστής των printf, scanf για τύπο δεδοµένων float είναι %f (αντί για %d στους ακεραίους) 2. Έπειτα γράψτε µια συνάρτηση main, που θα διαβάζει από την είσοδο τις τιµές των a,b,c (συντελεστές της εξίσωσης) και αφού εκτελέσει την συνάρτηση rizes θα εκτυπώνει τα κατάλληλα µηνύµατα µε τις ρίζες της β βάθµιας εξίσωης.

31 Ε. Ασκήσεις 2. Συνάρτηση init_array 1. Γράψτε την συνάρτηση: void init_array(int *pinakas, int n, int a, int b) που να αρχικοποιεί έναν πίνακα n ακεραίων, µε τυχαίους αριθµούς στο διάστηµα [a..b] 2. Ελέγξτε την ορθότητα της συνάρτησής σας µε κατάλληλα παραδείγµατα

32 Ε. Ασκήσεις 3. Συνάρτηση print_array Επεκτείνετε το πρόγραµµα της προηγούµενης άσκησης: 1. Γράψτε την συνάρτηση: void print_array(int *pinakas, int n) που να τυπώνει τα περιεχόµενα του πίνακα ακεραίων pinakas. 2. Ελέγξτε την ορθότητα της συνάρτησής σας µε κατάλληλα παραδείγµατα

33 Ε. Ασκήσεις 4. Συνάρτηση max_array Επεκτείνετε το πρόγραµµα της προηγούµενης άσκησης: 1. Γράψτε την συνάρτηση: int max_array(int *pinakas, int n) που να επιστρέφει τον µέγιστο στοιχείο του πίνακα ακεραίων pinakas 2. Ελέγξτε την ορθότητα της συνάρτησής σας µε κατάλληλα παραδείγµατα

34 Ε. Ασκήσεις 5. Ένα Πολύπλοκο Πρόγραµµα Συνεχίζοντας το προηγούµενο παράδειγµα, γράψτε µία συνάρτηση main η οποία: 1. Να δηλώνει έναν πίνακα ακεραίων 1000 θέσεων 2. Μέσα από ένα επαναλαµβανόµενο βρόχο να δίνει 6 επιλογές στον χρήστη: 1. Να εισάγει το µέγεθος του πίνακα 2. Να αρχικοποιεί µε τυχαίους αριθµούς από το a έως το b τα στοιχεία του πίνακα, όπου a και b είναι αριθµοί που ζητούνται από το χρήστη. 3. Να βρίσκει τον µέγιστο του πίνακα και να τον τυπώνει 4. Να τυπώνει όλα τα στοιχεία του πίνακα 5. Να κάνει έξοδο από τον επαναλαµβανόµενο βρόχο