Κατέβασμα παρουσίασης
Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε
1
ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΓΛΩΣΣΑ C
2. POINTERS (ΔΕΙΚΤΕΣ) & ΣΥΝΑΡΤΗΣΕΙΣ ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
2
1:#include <stdio.h> 2:main() 3:{ 4: float fl=3.14;
5: printf("%.2f\n", fl); 6:} ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
3
1:#include <stdio.h> 2:void somefunc(float fvar) 3:{ fvar=99.9;}
4:main() 5:{ float fl=3.14; 6: somefunc(fl); 7: printf("%.2f\n", fl); 8:} ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
4
1:#include <stdio.h> 2:main() 3:{ 4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl; 6: printf("fl's address=%u\n", addr);} ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
5
Τρόπος λειτουργίας των pointers (1)
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
6
Τρόπος λειτουργίας των pointers (2)
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
7
Pointers (Δείκτες) Η μνήμη ενός Η/Υ αποτελείται από θέσεις και κάθε θέση προσδιορίζεται από μια μοναδική διεύθυνση. Οι διευθύνσεις ξεκινούν από 0 μέχρι μια μέγιστη τιμή που εξαρτάται από το ποσό της εγκατεστημένης μνήμης. Ένα μέρος της μνήμης χρησιμοποιείται από το λειτουργικό σύστημα. Όταν εκτελούμε ένα πρόγραμμα ο κώδικας και τα δεδομένα του προγράμματος χρησιμοποιούν ένα διαφορετικό τμήμα της μνήμης. Όταν δηλώνουμε μια μεταβλητή σε ένα πρόγραμμα της C, o compiler κρατά μια μοναδική διεύθυνση μνήμης για την μεταβλητή αυτή. Ο compiler συσχετίζει την διεύθυνση με το όνομα της μεταβλητής. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
8
Η διεύθυνση μνήμης χρησιμοποιείται, αλλά είναι κρυμμένη από το χρήστη.
Όταν το πρόγραμμα χρησιμοποιεί το όνομα της μεταβλητής, αυτόματα κάνει προσπέλαση στην αντίστοιχη θέση μνήμης. Η διεύθυνση μνήμης χρησιμοποιείται, αλλά είναι κρυμμένη από το χρήστη. 1001 1002 1003 1004 rate ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
9
Έστω το όνομα rate με τιμή=100
Δημιουργία δείκτη Η διεύθυνση της μεταβλητής είναι ένας αριθμός τον οποίο μπορούμε να διαχειριστούμε όπως οποιονδήποτε αριθμό. Αν είναι γνωστή η διεύθυνση μιας μεταβλητής, μπορούμε να δημιουργήσουμε μια δεύτερη μεταβλητή στην οποία να αποθηκεύσουμε την διεύθυνση της πρώτης. Το πρώτο βήμα είναι να δηλώσουμε μια μεταβλητή που θα κρατά αυτή την διεύθυνση. Έστω το όνομα rate με τιμή=100 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
10
1001 1002 1003 1004 ? 100 rate p_rate Αρχικά η μεταβλητή p_rate δεν έχει κάποια τιμή (uninitialized). Της έχει εκχωρηθεί μια θέση μνήμης αλλά η τιμή της είναι απροσδιόριστη (undetermined) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
11
Το επόμενο βήμα είναι να αποθηκευθεί η διεύθυνση της μεταβλητής rate στην p_rate. Επειδή η p_rate περιέχει τη διεύθυνση της rate θα δείχνει στην διεύθυνση μνήμης της rate (p_rate points to rate ή is a pointer to rate). Συνοψίζοντας ένας δείκτης (pointer) είναι μια μεταβλητή που περιέχει τη διεύθυνση μνήμης μιας άλλης μεταβλητής. 1001 1002 1003 1004 1003 100 p_rate rate ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
12
Pointers Μια μεταβλητή που μπορεί να αποθηκεύσει τη διεύθυνση μνήμης μιας άλλης μεταβλητής 0x2000 chPtr 0x3A15 0x1FFE 0x1FFF 0x2000 0x2001 0x2002 etc ‘B’ ch ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
13
Δήλωση δεικτών int *p_rate
Ένας pointer είναι μια αριθμητική μεταβλητή και πρέπει να οριστεί πριν χρησιμοποιηθεί. Το όνομά του δηλώνεται όπως και οι υπόλοιπες μεταβλητές δηλ. έχει τύπο , όνομα και ένα ειδικό σύμβολο το * για να ξεχωρίζει από τις απλές μεταβλητές int *p_rate Ένας pointer μέχρι να του αποδοθεί μια τιμή είναι μη χρήσιμος. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
14
p_rate = &rate address-of operator &
Η διεύθυνση δεν αποδίδεται στο δείκτη δια μαγείας!! Το πρόγραμμα πρέπει να τοποθετήσει μια τιμή χρησιμοποιώντας τον τελεστή απόδοσης διεύθυνσης address-of operator & Όταν ο τελεστής & τοποθετείται μπροστά από το όνομα μιας μεταβλητής επιστρέφει τη διεύθυνσή της. p_rate = &rate ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
15
ΠΡΟΣΟΧΗ σε pointers που δεν έχουν αρχικοποιηθεί!
int *numPtr; ??? numPtr ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
16
Χρήση pointers ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
17
ΔΕΙΚΤΕΣ (pointers) Τα προβλήματα που αντιμετωπίζουν οι χρήστες με τους δείκτες προκύπτουν καταρχήν από την ερμηνεία του όρου μεταβλητή (variable) στα προγράμματα. Κάθε μεταβλητή είναι μια περιοχή θέσεων μνήμης που κρατά τις διαδοχικές τιμές της μεταβλητής, χρησιμοποιώντας ένα συμβολικό όνομα. Το μέγεθος αυτής της περιοχής μνήμης εξαρτάται από τον τύπο της μεταβλητής. Η δήλωση της μεταβλητής πληροφορεί τον compiler της γλώσσας προγραμματισμού για το όνομα και τον τύπο της μεταβλητής. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
18
Για τη δήλωση int k ο compiler :
δεσμεύει 2 bytes μνήμης και ενημερώνει ένα συμβολικό πίνακα ότι το σύμβολο k θα χρησιμοποιήσει 2 bytes της μνήμης κρατώντας τη διεύθυνση του 1ου από τα 2 bytes της περιοχής που καταλαμβάνει το k. αν αργότερα στο πρόγραμμα εμφανιστεί η εντολή: k=2 ; κατά την εκτέλεση του προγράμματος η τιμή 2 θα τοποθετηθεί στη θέση μνήμης που δεσμεύει το k. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
19
με το object k συσχετίζονται 2 τιμές :
Η γλώσσα C θεωρεί τέτοιες αναφορές σε μεταβλητές σαν αντικείμενα (objects) με το object k συσχετίζονται 2 τιμές : η τιμή που αποθηκεύεται (η τιμή της μεταβλητής π.χ. 2) η τιμή της θέσης μνήμης δηλ. Η ΔΙΕΥΘΥΝΣΗ της μεταβλητής k. ορισμένες αναφορές χρησιμοποιούν για τις 2 αυτές τιμές τις εκφράσεις lvalue και rvalue ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
20
Παραδείγματα int j, k; … k = 2; j = 7; γραμμή 1 k = j; γραμμή 2
στην γραμμή 1 ο compiler ερμηνεύει το j ως τη διεύθυνση της μεταβλητής j (lvalue) και δημιουργεί τον απαραίτητο κώδικα για να αντιγράψει την τιμή 7 σ’ αυτή τη διεύθυνση στην γραμμή 2 ο compiler ερμηνεύει το j ως rvalue και αναφέρεται στην τιμή που είναι αποθηκευμένη στην μεταβλητή j ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
21
μια τέτοια μεταβλητή ονομάζεται pointer variable (μεταβλητή δείκτης).
Ας υποθέσουμε ότι για κάποιο λόγο θέλουμε μια μεταβλητή να κρατήσει την lvalue (δηλ. τη διεύθυνση) το μέγεθος της περιοχής που χρειαζόμαστε για να αποθηκεύσουμε μια τέτοια τιμή εξαρτάται από το σύστημα συνήθως χρειαζόμαστε 2 bytes αν και το μέγεθος δεν είναι σημαντικό για την κατανόηση του προβλήματος μια τέτοια μεταβλητή ονομάζεται pointer variable (μεταβλητή δείκτης). ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
22
Δείκτες στη γλώσσα C int *ptr
Δίνουμε επίσης έναν ΤΥΠΟ στο δείκτη για να αναφερθούμε στον τύπο δεδομένων που αποθηκεύονται στη διεύθυνση που δείχνει ο δείκτης π.χ. int *ptr ptr είναι το όνομα της μεταβλητής * ενημερώνει τον compiler ότι είναι δείκτης int δηλώνει ότι θα χρησιμοποιήσουμε τη μεταβλητή-δείκτη για να αποθηκεύσουμε τη διεύθυνση ενός ακεραίου (integer) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
23
Στην προηγούμενη δήλωση δεν ο ptr δεν έχει τιμή δηλ
Στην προηγούμενη δήλωση δεν ο ptr δεν έχει τιμή δηλ. δεν έχει αποθηκευθεί κάποια διεύθυνση μνήμης στον ptr για να εξασφαλισθεί ότι ο δείκτης δεν δείχνει σε καμία μεταβλητή πρέπει να χρησιμοποιείται η τιμή NULL π.χ. ptr = NULL ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
24
όταν δηλώνεται ένας pointer, συνιστάται πάντοτε να αρχικοποιείται (initialize) σε NULL (είναι μια ειδική pointer constant) int *numPtr = NULL; NULL numPtr ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
25
Παράδειγμα Θέλουμε να αποθηκεύσουμε στον ptr τη διεύθυνση της ακέραιας μεταβλητής k ptr = &k ; ο τελεστής & ανακτά την lvalue (address) της μεταβλητής k παρόλο που το όνομα της μεταβλητής k βρίσκεται στο δεξιό μέλος της έκφρασης!!! ….και την αντιγράφει σαν περιεχόμενο της μεταβλητής ptr. Ο ptr δείχνει στη μεταβλητή k ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
26
The “ dereferencing operator * "
*ptr = 7; η τιμή 7 αντιγράφεται στη διεύθυνση που δείχνει ο ptr αν ο ptr δείχνει στη μεταβλητή k τότε η παραπάνω έκφραση αναθέτει στην k την τιμή 7. Αν χρησιμοποιούμε το * με αυτόν τον τρόπο αναφερόμαστε στη θέση που δείχνει ο δείκτης και όχι κατευθείαν στο δείκτη. printf("%d\n",*ptr); εμφανίζεται στην οθόνη η ακέραια τιμή που είναι αποθηκευμένη στη διεύθυνση που δείχνει η ptr. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
27
int *ptr ; *ptr =2 ; εφόσον ο δείκτης ptr δείχνει σε ακέραιο ο compiler ξέρει ότι θα αντιγράψει 2 bytes στη θέση μνήμης που δείχνει ο ptr. Καθορίζοντας τον τύπο δεδομένων που θα δείχνει ο δείκτης ο compiler μπορεί να υπολογίσει και ένα πλήθος άλλων σχετικών παραμέτρων. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
28
Ο τελεστής * επιτρέπει στους pointers να έχουν πρόσβαση στις μεταβλητές στις οποίες δείχνουν είναι γνωστός και ως “dereferencing operator” (τελεστής έμμεσης αναφοράς) δεν θα πρέπει να συγχέεται με το * που χρησιμοποιείται στη δήλωση του δείκτη ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
29
Pointers και ο τελεστής
παράδειγμα: char c = ’A’; char *cPtr = NULL; Αλλάζει την τιμή της μεταβλητής στην οποία δείχνει ο cPtr cPtr = &c; *cPtr = ’B’; cPtr: 0x2004 NULL A c: 0x2000 B 0x2000 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
30
Παράδειγμα #include <stdio.h> int main() { int i;
int *p; /* a pointer to an integer */ p = &i; *p=5; printf("%d %d %d\n", i, *p); return 0; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
31
Easy Steps to Pointers Step 1: Declare the variable to be pointed to
int num; char ch = ‘A’; float x; num: ch: ‘A’ x: ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
32
Easy Steps to Pointers (cont)
Step 2: Declare the pointer variable int num; char ch = ‘A’; float x; numPtr: NULL chPtr: NULL int* numPtr = NULL; char *chPtr = NULL; float * xPtr = NULL; xPtr: NULL num: ch: ‘A’ x: ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
33
Easy Steps to Pointers (cont)
Step 3: Assign address of variable to pointer int num; char ch = ‘A’; float x; numPtr: addr of num chPtr: addr of ch int* numPtr = NULL; char *chPtr = NULL; float * xPtr = NULL; xPtr: addr of x numPtr = # num: chPtr = &ch; xPtr = &x; ch: ‘A’ x: Ένας τύπος δείκτη πρέπει να αντιστοιχεί στον τύπο της μεταβλητής στην οποία δείχνει ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
34
Easy Steps to Pointers (cont)
Step 4: De-reference the pointers int num; char ch = ‘A’; float x; numPtr: addr of num chPtr: addr of ch int* numPtr = NULL; char *chPtr = NULL; float * xPtr = NULL; xPtr: addr of x numPtr = # chPtr = &ch; xPtr = &x; num: 65 ch: ‘A’ *xPtr = 0.25; *numPtr = *chPtr; x: 0.25 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
35
Έστω ότι ο δείκτης ptr δείχνει στον πρώτο από αυτούς τους ακέραιους.
Θεωρείστε ένα block 20 θέσεων μνήμης σε μια στήλη, όπου μπορούν να αποθηκευθούν 10 ακέραιοι αριθμοί. Έστω ότι ο δείκτης ptr δείχνει στον πρώτο από αυτούς τους ακέραιους. Έστω ότι ο πρώτος ακέραιος βρίσκεται στη διεύθυνση μνήμης 100 (δεκαδικός). Τι θα συμβεί αν γράψουμε ptr+1 ; Επειδή ο compiler ξέρει ότι ο ptr είναι δείκτης και δείχνει σε ακέραιο (2 bytes) προσθέτει 2 στον ptr αντί για 1 έτσι ώστε να δείχνει στον επόμενο ακέραιο, στη διεύθυνση μνήμης 102. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
36
Η πρόσθεση αυτή λέγεται πρόσθεση με χρήση αριθμητικής δεικτών.
Αυτό ισχύει για κάθε τύπο δεδομένων (float, double, structure, τύπο δεδομένων που ορίζει ο χρήστης) ανάλογα με τις θέσεις μνήμης που δεσμεύει ο κάθε τύπος δεδομένων. Η πρόσθεση αυτή λέγεται πρόσθεση με χρήση αριθμητικής δεικτών. Παρόμοια λειτουργούν και οι τελεστές ++ στις σχέσεις ++ptr (pre) και ptr++ (post) αυξάνοντας τη διεύθυνση κατά το ποσό που δίνει η συνάρτηση sizeof(type), όπου type είναι ο τύπος αντικειμένου (object) που δείχνει ο δείκτης ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
37
ΠΡΑΞΕΙΣ (ΛΕΙΤΟΥΡΓΙΕΣ) ΜΕ ΔΕΙΚΤΕΣ
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
38
Συναρτήσεις που επιστρέφουν ΠΕΡΙΣΣΟΤΕΡΕΣ από μία τιμές
Συναρτήσεις που επιστρέφουν ΠΕΡΙΣΣΟΤΕΡΕΣ από μία τιμές ΔΕΝ ορίζεται τύπος για τη συνάρτηση Στο πρωτότυπο και στον ορισμό της συνάρτησης χρησιμοποιούμε το * για όσες μεταβλητές θέλουμε να «επιστρέψουν» ΤΙΜΗ ΣΤΟ ΚΥΡΙΩΣ ΠΡΟΓΡΑΜΜΑ Στην κλήση της συνάρτησης οι αντίστοιχες μεταβλητές δηλώνονται με & ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
39
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
40
Διευθύνσεις μνήμης - Δείκτες
Ο τελεστής διεύθυνσης & χρησιμοποιείται σε συναρτήσεις για να περάσουμε τις διευθύνσεις των μεταβλητών (π.χ. scanf) Η συνάρτηση scanf απαιτεί την διεύθυνση της θέσης μνήμης επειδή πρέπει να γνωρίζει σε ποιά θέση μνήμης θα βάλει την τιμή που δόθηκε από το πληκτρολόγιο ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
41
Συναρτήσεις – Κλήσεις Το * στο πρωτότυπο μιας συνάρτησης δηλώνει ότι η μεταβλητή που ακολουθεί πρόκειται να «ΚΡΑΤΗΣΕΙ» μια διεύθυνση μνήμης. Ο τελεστής διεύθυνσης & δηλώνει ότι κατά την κλήση της συνάρτησης θα μεταβιβασθεί στην αντίστοιχη μεταβλητή της συνάρτησης ένα αντίγραφο της διεύθυνσης της πραγματικής μεταβλητής. Ο τελεστής * στη συνάρτηση δηλώνει ότι στη διεύθυνση που είναι αποθηκευμένη στην μεταβλητή που ακολουθεί το * θα αποδοθεί ή θα διαβαστεί μια τιμή. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
42
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
43
Παράμετροι αναφοράς (Reference Parameters)
Reference parameters allow a function to access the original arguments Program output: void doubleNum ( int *refVar ); void main ( void ) { int val = 4; cout << “val is “ << val << endl; doubleNum ( &val ); cout << “now val is “ << val << endl; } void doubleNum ( int *refVar ) *refVar *= 2; val is 4 now val is 8 val 4 Use ampersand 8 Points to variable val pointerrefVar Changes to the reference parameter are also made to the argument
44
Pass by Reference Pass by value Pass by refence val val 4 4 8 valVar
void doubleNum ( int valVar ); void main( ) { int val = 4; doubleNum ( val ); cout << val << endl; } void doubleNum ( int valVar ) valVar *= 2; void doubleNum ( int *refVar ); void main( ) { int val = 4; doubleNum ( &val ); cout << val << endl; } void doubleNum ( int *refVar ) *refVar *= 2; val val 4 4 8 valVar refVar 4 8 Value of val is copied to valVar valVar is initialized to 4 Variable val is not changed refVar points to variable val Directly accesses val Variable val is changed ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
45
Παράδειγμα Να γραφεί μια συνάρτηση (swap) που θα εναλλάσσει το περιεχόμενο δύο θέσεων της μνήμης. Στη συνέχεια να γραφεί ένα πρόγραμμα σε γλώσσα C που θα χρησιμοποιεί τη συνάρτηση. Οι τιμές που περιέχονται στις θέσεις μνήμης είναι ακέραιοι αριθμοί. swap x: 1 y: 2 x: 2 y: 1 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
46
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
47
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
48
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; tmp: a: 1 b: 2 x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
49
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; 1 tmp: a: 1 b: 2 x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
50
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; tmp: 1 a: 2 b: 2 x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
51
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; tmp: 1 a: 2 b: 1 x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
52
#include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a;
Bad swap #include <stdio.h> void swap1(int a, int b) { int tmp; tmp = a; a = b; b = tmp; return; } int main() int x = 1, y = 2; swap1(x, y); printf(“%d %d\n”, x, y); return 0; tmp: 1 a: 2 b: 1 x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
53
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
54
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
55
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; tmp: a: addr of x b: addr of y x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
56
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; tmp: 1 a: addr of x b: addr of y x: 1 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
57
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; tmp: 1 a: addr of x b: addr of y x: 2 y: 2 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
58
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; 1 tmp: a: addr of x b: addr of y x: 2 y: 1 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
59
#include <stdio.h> void swap2(int* a, int* b) { int tmp;
Good swap #include <stdio.h> void swap2(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; return; } int main() int x = 1, y = 2; swap2(&x, &y); printf(“%d %d\n”, x, y); return 0; x: 2 y: 1 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
Παρόμοιες παρουσιάσεις
© 2024 SlidePlayer.gr Inc.
All rights reserved.