Δείκτες (Pointers) (1/2) ΗΥ150 Προγραμματισμός

Σχετικά έγγραφα
ΗΥ-150. Προγραμματισμός

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

ΗΥ-150 Προγραμμαηιζμός Δείκηες (Pointers) (1/2)

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

Προγραμματισμός Επιπλέον στοιχεία της C++

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

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

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

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

Πανεπιστήµιο Πατρών ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΙΙ (C++) είκτες και Συµβολοσειρές (Pointers. & Strings)

Διάλεξη 9η: Πίνακες (arrays)

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δείκτες και Συναρτήσεις (Κεφάλαιο 11, KNK-2ED)

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

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

ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

Προαπαιτούμενες Ασκήσεις 5 ου Εργαστηρίου. Dose stoixeio (integer) : 25 Found stoixeio in position 7 Dose stoixeio (integer) :94 Value not found

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

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

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

Προγραµµατισµός. Επιπλέον στοιχεία της C

Οντοκεντρικός Προγραμματισμός

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

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

Στόχοι και αντικείμενο ενότητας. Πέρασμα Πίνακα σε Συνάρτηση (συν.) Πέρασμα Πίνακα σε Συνάρτηση. #8.. Ειδικά Θέματα Αλγορίθμων

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

Αναφορές, είκτες και Αλφαριθμητικά

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Σημειώσεις δεύτερης εβδομάδας

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

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

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

Αντικειμενοστραφείς Γλώσσες Προγραμματισμού C++ / ROOT

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

Προγραμματισμός Η/Υ. Ενότητα 8: Ειδικά Θέματα Αλγορίθμων

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

Η γλώσσα C. Δείκτες (pointers)

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

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

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

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

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 8 η : Συναρτήσεις Χειµερινό Εξάµηνο 2011

ΚΥΠΡΙΑΚΗ ΕΤΑΙΡΕΙΑ ΠΛΗΡΟΦΟΡΙΚΗΣ CYPRUS COMPUTER SOCIETY ΠΑΓΚΥΠΡΙΟΣ ΜΑΘΗΤΙΚΟΣ ΔΙΑΓΩΝΙΣΜΟΣ ΠΛΗΡΟΦΟΡΙΚΗΣ 24/3/2007

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

C: Από τη Θεωρία στην Εφαρμογή

Lab 1: C/C++ Pointers and time.h. Panayiotis Charalambous 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Lab 1: C/C++ Pointers and time.h. Panayiotis Charalambous 1

Διάλεξη 10η: Πολυδιάστατοι Πίνακες

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

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

HY150a Φροντιστήριο 3 24/11/2017

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

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

Η γλώσσα προγραμματισμού C Οι συναρτήσεις στη C (2)

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

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

Εισαγωγή στον Προγραμματισμό (με. τη C)

Η εντολή if-else. Η απλή μορφή της εντολής if είναι η ακόλουθη: if (συνθήκη) { Η γενική μορφή της εντολής ifelse. εντολή_1; εντολή_2;..

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

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

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

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

12. Συναρτήσεις (Μέρος ΙI)

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. Δείκτες (Διάλεξη 14)

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

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

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

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

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

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. (Διάλεξη 14) Παράδειγμα: Αλλαγή τιμής μεταβλητής μόνο τοπικά

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

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

17TimeThis.h function returns reference pointer to same object { return *this; }

Στόχοι και αντικείμενο ενότητας. Τύπος πίνακα. Τύπος πίνακα (συν.) #6. Πίνακες και Δείκτες

Transcript:

ΗΥ-150 Προγραμματισμός Δείκτες (Pointers) (1/2)

Δείκτες Τι είναι: τύπος μεταβλητών (όπως integer) Τι αποθηκεύουν: την διεύθυνση στη μνήμη άλλων μεταβλητών Τι χρειάζονται: Κυρίως, για δυναμική διαχείριση μνήμης και δυναμικές δομές δεδομένων Call-by-reference Στενή σχέση με τους πίνακες Πηγή πολλών λαθών που δύσκολα ανιχνεύονται 2

Δείκτες int Counter = 7; int *PointerToCounter; Όνομα Θέση Μνήμης Τιμή PointerToCounter = &Counter; Counter 231000 7 count 7 countptr count 7 PointerToCounter 234000 231000 3

Δήλωση Δεικτών: Το * χρησιμοποιείται για να δηλώσει δείκτη int *myptr; Ορίζει δείκτη σε int (pointer of type int *) Δήλωση πολλών μεταβλητών τύπου δείκτη απαιτεί τη χρήση ενός * μπροστά από κάθε μία: int *myptr1, *myptr2; Μπορούμε να δηλώσουμε δείκτη σε οποιοδήποτε είδος μεταβλητής (ακόμα και άλλο δείκτη) double *myptr2; char **myptr2; 4

Τελεστές Δεικτών &μεταβλητή q = &a; Επέστρεψε την διεύθυνση στην οποία είναι αποθηκευμένη η μεταβλητή *δείκτης a = *q; Επέστρεψε τα περιεχόμενα της διεύθυνσης στην οποία δείχνει ο δείκτης 5

Τελεστές Δεικτών & (address operator) int y = 5; int *yptr; yptr = &y; // O yptr παίρνει την διεύθυνση y yptr y 5 yptr 500000 600000 y 600000 5 Ηδιεύθυνση του y είναι η τιμή της yptr 6

Τελεστές Δεικτών * (indirection/dereferencing operator) int y = 5; int *yptr; yptr = &y; *yptr = *yptr * 2; Μπορώ να αλλάζω την τιμή των μεταβλητών με τη βοήθεια δεικτών Ητιμήτουy γίνεται ίση με 10 Η μεταβλητή y αλλάζει τιμή, χωρίςστονκώδικαναφαίνεται αυτό άμεσα σε μια εντολή που εμφανίζει την y! H y δηλαδή, αποκτά ένα «ψευδώνυμο»: το *yptr * και & είναι ανάποδα και αλληλοακυρώνονται 7

Ανάθεση δεικτών Ένας δείκτης μπορεί να ανατεθεί σε άλλο δείκτη ίδιου τύπου: int a = 4; int * p; p = &a; int * q = p; Ηεντολήint * q = p; ορίζει το q ως δείκτη σε int και του δίνει αρχική τιμή το p. Τα q και p δείχνουν την ίδια θέση μνήμης και, άρα, *q και *p δείχνουν στην ίδια μεταβλητή (η a). 8

Αρχικοποίηση δεικτών Ένας δείκτης που δεν του αποδοθεί αρχική τιμή δείχνει σε τυχαία περιοχή μνήμης. Η προσπέλασηστηντυχαίαθέσημνήμηςαυτήθαπροκαλέσει σφάλμα εκτέλεσης, αν η συγκεκριμένη θέση δεν έχει δοθεί από το λειτουργικό σύστημα στο πρόγραμμά. Αν έχει δοθεί, και γράψουμε στη θέση μνήμης αυτή, θα πανωγράψουμε άλλη δική μας μεταβλητή χωρίς σφάλμα εκτέλεσης. Σε ένα οποιοδήποτε δείκτη μπορεί να γίνει απόδοση της τιμής 0. Το 0 δεν αποτελεί αριθμό θέσης μνήμης και, επομένως, η ανάθεση αυτή υποδηλώνει ότι ο δείκτης δε δείχνει σε κανένα αντικείμενο. Σε τέτοιο δείκτη (null pointer) η δράσητου(*) δεν επιτρέπεται (προκαλεί λάθος κατά την εκτέλεση αλλά όχι κατά τη μεταγλώττιση του προγράμματος). Η σύγκριση ενός άγνωστου δείκτη (π.χ. όρισμα συνάρτησης) με το 0 πρέπει να προηγείται οποιασδήποτε απόπειρας προσπέλασης της θέσης μνήμης στην οποία θεωρούμε ότι δείχνει. Προσέξτε ότι σε αυτό το σημείο υπάρχει μία βασική διαφορά με την αναφορά: ένας δείκτης μπορεί να μη συνδέεται με κανένα αντικείμενο ενώ, αντίθετα, μία αναφορά είναι οπωσδήποτε συνδεδεμένη με κάποια ποσότητα. 9

1 /* 2 Using the & and * operators */ 3 #include <stdio.h> 4 5 int main() 6 { 7 int a; /* a is an integer */ 8 int *aptr; /* aptr is a pointer to an integer */ 9 10 a = 7; 11 aptr = &a; /* aptr set to address of a */ 12 13 printf( "The address of a is %p" 14 "\nthe value of aptr is %p", &a, aptr ); 15 16 printf( "\n\nthe value of a is %d" 17 "\nthe value of *aptr is %d", a, *aptr ); 18 19 printf( "\n\nshowing that * and & are inverses of " 20 "each other.\n&*aptr = %p" 21 "\n*&aptr = %p\n", &*aptr, *&aptr ); 22 23 return 0; 24 } The address of a is 0012FF88 The value of aptr is 0012FF88 The address of a is the value of aptr. The * operator returns an alias to what its operand points to. aptr points to a, so *aptr returns a. Notice how * and & are inverses The value of a is 7 The value of *aptr is 7 Proving that * and & are complements of each other. &*aptr = 0012FF88 *&aptr = 0012FF88

1 /* 2 Cube a variable using call-by-reference 3 with a pointer argument */ 4 5 #include <stdio.h> 6 7 void cubebyreference( int * ); /* prototype */ 8 9 int main() 10 { 11 int number = 5; 12 13 printf( "The original value of number is %d", number ); 14 cubebyreference( &number ); 15 printf( "\nthe new value of number is %d\n", number ); 16 17 return 0; 18 } 19 20 void cubebyreference( int *nptr ) 21 { 22 *nptr = *nptr * *nptr * *nptr; /* cube number in main */ 23 } The original value of number is 5 The new value of number is 125 Notice that the function prototype takes a pointer to an integer (int *). Notice how the address of number is given - cubebyreference expects a pointer (an address of a variable). Inside cubebyreference, *nptr is used (*nptr is number).

Sort με χρήση της Swap void swap( int *n1, int *n2) { int temp; } temp = *n1; *n1 = *n2; *n2 = temp; int x = 10, y=20; swap(&x,&y); 12

1 /* Fig. 7.15: fig07_15.c 2 This program puts values into an array, sorts the values into 3 ascending order, and prints the resulting array. */ 4 #include <stdio.h> 5 #define SIZE 10 6 void bubblesort( int *, const int ); 7 void swap( int *, int * ); 8 int main() 9 { 10 11 int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 12 int i; sort gets passed the address 13 14 printf( "Data items in original order\n" ); 15 16 for ( i = 0; i < SIZE; i++ ) 17 printf( "%4d", a[ i ] ); 18 of array elements (pointers). The name of an array is a pointer. 19 bubblesort( a, SIZE ); /* sort the array */ 20 printf( "\ndata items in ascending order\n" ); 21 22 for ( i = 0; i < SIZE; i++ ) 23 printf( "%4d", a[ i ] ); 24 25 printf( "\n" ); 26 27 return 0; 28 } 29 30 void bubblesort( int *array, const int size ) 31 { 32

33 int pass, j; 34 for ( pass = 0; pass < size - 1; pass++ ) 35 36 for ( j = 0; j < size - 1; j++ ) 37 38 if ( array[ j ] > array[ j + 1 ] ) 39 swap( &array[ j ], &array[ j + 1 ] ); 40 } 41 42 void swap( int *element1ptr, int *element2ptr ) 43 { 44 int hold = *element1ptr; 45 *element1ptr = *element2ptr; 46 *element2ptr = hold; 47 } Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45

Αριθμητική Δεικτών Στους δείκτες μπορούμε να πραγματοποιούμε αριθμητικές πράξεις: ++ ή - Ο δείκτης δείχνει στο επόμενο ή προηγούμενο αντικείμενο, δηλ. αν είναι δείκτης σε ακέραιο στον επόμενο ή προηγούμενο ακέραιο Αντίστοιχα για + ή +=, - ή -= Οι δείκτες μπορούν να αφαιρούνται ο ένας από τον άλλο Όλες αυτές οι πράξεις δεν έχουν νόημα εκτός αν πραγματοποιούνται πάνω δείκτη που δείχνει στα στοιχεία ενός πίνακα 15

Αριθμητική Δεικτών Πίνακας 5 στοιχείων τύπου int σε μηχανή με 4 byte ints int v[5]; int *vptr; vptr = &v[0] ή vptr = v; //δείχνει στο πρώτο στοιχείο v[0] vptr += 2; //vptr στο 3008 //vptr στο 3000 vptr δείχνει στο v[ 2 ] (αύξηση κατά 2), μια και η μηχανή έχει 4 byte ints, οπότε δείχνει 3008 location 3000 3004 3008 3012 3016 v[0] v[1] v[2] v[3] v[4] pointer variable vptr 16

Σχέση μεταξύ πινάκων και δεικτών Στοιχείο b[ 3 ] Μπορούμε να το πάρουμε σαν *( bptr + 3 ) Σαν bptr[ 3 ] bptr[ 3 ] == b[ 3 ] Με αριθμητική δεικτών: *( b + 3 ) 17

Διεύθυνση Πινάκων και Δείκτες int *a; a δείκτης σε ακέραιο Δεσμεύεται μνήμη μόνο για την αποθήκευση του a (της διεύθυνσης) Μπορούμε να αλλάξουμε την διεύθυνση που δείχνει ο a int b[10]; b σταθερή διεύθυνση (δείκτης) σε ακέραιο Δεσμεύεται μνήμη για 10 ακέραιους Δεν μπορούμε να αλλάξουμε την διεύθυνση στην οποία αντιστοιχεί ο b 18

Πίνακες και Δείκτες Μπορούμε να περνάμε δείκτες σε συναρτήσεις που περιμένουν πίνακες και αντίστροφα. Σε κάθε περίπτωση περνάμε απλώς μία διεύθυνση μνήμης. Το παρακάτω γίνεται δεκτό: void f(int a[]); void q(int *b); int main() { int *c; int d[10]; f(c); q(d) } 19

Παράδειγμα - ptrarithm2.c (Ι) int n[10] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 1}, *p, c; // First way to traverse the array printf("first way to index the array.\n"); for (c=0; c < 10; c++) printf("n[%d] = %d\n", c, n[c]); printf("\nsecond way to index the array, through pointer arithmetic.\n"); for (c=0; c < 10; c++) printf("n[%d] = %d\n", c, *(n+c)); 20

Παράδειγμα - ptrarithm2.c (ΙΙ) printf("\nthird way to index the array, through pointers arithmetic.\n"); // We set the pointer to the beginning of the array p = n; for (c=0; c < 10; c++) printf("n[%d] = %d\n", c, *(p+c)); printf("\nfourth way to index the array, through pointers arithmetic.\n"); p = n; for (c=0 ; c < 10; c++) printf("n[%d] = %d, %d\n", c, *(p++), p); 21

ΗΥ-150 Προγραμματισμός Δείκτες (Pointers) (2/2)

Μετατροπή Τύπων και Δείκτες Ο τύπος του αντικειμένου στο οποίο δείχνει ο δείκτης χρειάζεται για την σωστή αριθμητική δεικτών Όλοι οι δείκτες, ανεξάρτητα του αντικειμένου που δείχνουν, απαιτούν την ίδια μνήμη για την αποθήκευσή τους Η μετατροπή τύπων από ένα τύπο δείκτη σε άλλο τύπο δείκτη δεν αλλάζει τα περιεχόμενα του δείκτη: int *aptr; float *bptr; aptr = (int *)bptr; 23

Παραδείγματα types.c, types2.c //types.c #include <stdio.h> int main() { int *a; double *b; float *c; float (*d)[10]; float da[10]; printf("size of a = %d\n", sizeof(a)); printf("size of b = %d\n", sizeof(b)); printf("size of c = %d\n", sizeof(c)); printf("size of d = %d\n", sizeof(d)); printf("size of *d = %d\n", sizeof(*d)); printf("size of da = %d\n", sizeof(da)); //types2.c #include <stdio.h> int main() { int *a,n,array[10]; double *b; // Doing pointer arithmetic on a as an int * a = array; for (n=0; n < 10; n++) printf("address of a is %d\n", a++); putchar('\n'); // Doing pointer arithmetic on b as an double * // Notice that if I try to access the *b I may get // a segmentation fault here, 'cause b points out of // the array } return 0; } b = (double *)array; for (n=0; n < 10; n++) printf("address of b is %d\n", b++); return 0; 24

Χρήση του const με δείκτες const qualifier Η μεταβλητή δεν αλλάζει Χρησιμοποιείστε το const αν η συνάρτηση δεν χρειάζεται να αλλάζει τη μεταβλητή Η προσπάθεια αλλαγής μιας const μεταβλητής παράγει λάθος const pointers Δείχνει σε μια σταθερή διεύθυνση μνήμης Πρέπει να αρχικοποιείται όταν δηλώνεται: int *const myptr = &x; Type int *const constant pointer to an int const int *myptr = &x; Regular pointer to a const int const int *const Ptr = &x; const pointer to a const int x can be changed, but not *Ptr 25

1 /* 2 Attempting to modify a constant pointer to 3 non-constant data */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 int x, y; 10 11 int * const ptr = &x; /* ptr is a constant pointer to an 12 integer. An integer can be modified 13 through ptr, but ptr always points 14 to the same memory location. */ 15 *ptr = 7; 16 ptr = &y; 17 18 return 0; 19 } Changing *ptr is allowed x is not a constant. Changing ptr is an error ptr is a constant pointer. Error E2024 FIG07_13.c 16: Cannot modify a const object in function main *** 1 errors in Compile ***

Πίνακες από δείκτες Ένας πίνακας μπορεί να περιέχει και δείκτες Παράδειγμα: ένας πίνακας από strings char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; Περιέχει δείκτες στον 1 ο κάθε φορά χαρακτήρα char * κάθε στοιχείο του suit είναι δείκτης σε char Τα strings στην πραγματικότητα δεν αποθηκεύονται στον πίνακα suit, μόνο δείκτες αποθηκεύονται στον πίνακα suit[0] H e a r t s \0 suit[1] suit[2] suit[3] D i a m o n d s \0 C l u b s \0 S p a d e s \0 Το suit έχει σταθερό μέγεθος (ως πίνακας άλλωστε), αλλά τα αλφαριθμητικά μπορούν να έχουν όποιο μέγεθος επιθυμούμε 27

Παράδειγμα: Ανακάτεμα και μοίρασμα τράπουλας 28

1 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <time.h> 6 7 void shuffle( int [][ 13 ] ); 8 void deal( const int [][ 13 ], const char *[], const char *[] ); 9 10 int main() 11 { 12 const char *suit[ 4 ] = 13 { "Hearts", "Diamonds", "Clubs", "Spades" }; 14 const char *face[ 13 ] = 15 { "Ace", "Deuce", "Three", "Four", 16 "Five", "Six", "Seven", "Eight", 17 "Nine", "Ten", "Jack", "Queen", "King" }; 18 int deck[ 4 ][ 13 ] = { 0 }; 19 20 srand( time( 0 ) ); 21 22 shuffle( deck ); 23 deal( deck, face, suit ); 24 25 return 0; 26 } 27 28 void shuffle( int wdeck[][ 13 ] ) 29 { 30 int row, column, card; 31 32 for ( card = 1; card <= 52; card++ ) {

33 do { 34 row = rand() % 4; 35 column = rand() % 13; 36 } while( wdeck[ row ][ column ]!= 0 ); 37 38 wdeck[ row ][ column ] = card; 39 } 40 } 41 42 void deal( const int wdeck[][ 13 ], const char *wface[], 43 const char *wsuit[] ) 44 { 45 int card, row, column; 46 47 for ( card = 1; card <= 52; card++ ) 48 49 for ( row = 0; row <= 3; row++ ) 50 51 for ( column = 0; column <= 12; column++ ) 52 53 if ( wdeck[ row ][ column ] == card ) 54 printf( "%5s of %-8s%c", 55 wface[ column ], wsuit[ row ], 56 card % 2 == 0? '\n' : '\t' ); 57 57 } card % 2 == 0? '\n' : '\t' ); The numbers 1-52 are randomly placed into the deck array showing the position of card wdeck[row][column]. Searches deck for the card number, then prints the face and suit.

Six of Clubs Seven of Diamonds Ace of Spades Ace of Diamonds Ace of Hearts Queen of Diamonds Queen of Clubs Seven of Hearts Ten of Hearts Deuce of Clubs Ten of Spades Three of Spades Ten of Diamonds Four of Spades Four of Diamonds Ten of Clubs Six of Diamonds Six of Spades Eight of Hearts Three of Diamonds Nine of Hearts Three of Hearts Deuce of Spades Six of Hearts Five of Clubs Eight of Clubs Deuce of Diamonds Eight of Spades Five of Spades King of Clubs King of Diamonds Jack of Spades Deuce of Hearts Queen of Hearts Ace of Clubs King of Spades Three of Clubs King of Hearts Nine of Clubs Nine of Spades Four of Hearts Queen of Spades Eight of Diamonds Nine of Diamonds Jack of Diamonds Seven of Clubs Five of Hearts Five of Diamonds Four of Clubs Jack of Hearts Jack of Clubs Seven of Spades

Δείκτες σε συναρτήσεις Δείκτης σε συνάρτηση Περιέχει τη διεύθυνση του κώδικα της συνάρτησης Όπως ένας δείκτης δείχνει στο 1 ο στοιχείο ενός πίνακα Γιατί; Πολλές φορές δεν ξέρουμε τη συνάρτηση θέλουμε να καλέσουμε, μέχρι να τρέξουμε το πρόγραμμα (π.χ., αν η συνάρτηση που πρέπει να καλέσουμε καθορίζεται από την είσοδο). Πολλές φορές προγραμματίζουμε ή χρησιμοποιούμε συναρτήσεις βιβλιοθήκης οι οποίες χρησιμοποιούν άλλες υποσυναρτήσεις. Οι τελευταίες μπορεί να προμηθεύονται από τον χρήστη της βιβλιοθήκης, ώστε να αλλάζουν την συμπεριφορά της συνάρτησης, χωρίς να χρειάζεται να την ξαναμεταγλωττίσουμε. Απαραίτητες πολλές φορές για κατανοητό, ευανάγνωστο ή γρήγορο κώδικα. Αποφεύγουμε τις πολλές if/switch 32

Δείκτες σε συναρτήσεις Οι δείκτες σε συναρτήσεις Τα περνάμε σαν ορίσματα σε συναρτήσεις Αποθηκεύονται σε πίνακες Εκχωρούνται σε άλλους δείκτες Διαφορά 1 από τους υπόλοιπους δείκτες: «πρόσβαση» στα περιεχόμενά τους: *functionptr (*functionptr)(argument1, argument2) Σε αυτήν την περίπτωση καλείται η συνάρτηση της οποίας η διεύθυνση είναι αποθηκευμένη στον δείκτη Διαφορά 2 από τους υπόλοιπους δείκτες: ανάθεση διεύθυνσης μιας συνάρτησης και όχι μεταβλητής functionptr = &afunction; 33

Δήλωση Δεικτών σε Συναρτήσεις int (*funptr)(int, int) Ο τύπος της μεταβλητής funptr είναι «δείκτης σε συνάρτηση που παίρνει δύο ορίσματα τύπου int, και επιστρέφει int. int *funptr(int, int) Αυτό θα σήμαινε, ότι το funptr είναι τύπου «συνάρτηση που παίρνει δύο ορίσματα τύπου int, και επιστρέφει δείκτη σε int) int (*funptrarray[10])(int, int)) Τυπος του funptrarray: πίνακας από 10 δείκτες σε συναρτήσεις που παίρνουν δύο ορίσματα τύπου int και επιστρέφουν int 34

Παραδείγματα intfunction(inta, intb) { return a*b; } int main() { int (*funptr)(int, int); funptr = &function; printf( Calling the function returns %d\n, (*funptr)(4, 5)); return 0; } Δήλωση του δείκτη σε συνάρτηση Ανάθεση της διεύθυνσης μιας συνάρτησης Κλήση της συνάρτησης που είναι αποθηκευμένη στον δείκτη 35

Παράδειγμα Θυμηθείτε ότι η BubbleSort ταξινομεί ακεραίους βασιζόμενη σε συγκρίσεις μεταξύ τους. Αλλάξτε την BubbleSort ώστε να παίρνει ως όρισμα την συνάρτηση σύγκρισης δύο ακεραίων και να την χρησιμοποιεί για ταξινόμηση. Καλέστε την BubbleSort έτσι ώστε να ταξινομεί ακεραίους και κατά αύξοντα σειρά και κατά φθίνουσα 36

1 2 3 #include <stdio.h> 4 #define SIZE 10 5 void bubble( int [], const int, int (*)( int, int ) ); 6 int ascending( int, int ); 7 int descending( int, int ); 8 9 int main() 10 { 11 12 int order, 13 counter, 14 a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 15 16 printf( "Enter 1 to sort in ascending order,\n" 17 "Enter 2 to sort in descending order: " ); 18 scanf( "%d", &order ); 19 printf( "\ndata items in original order\n" ); 20 21 for ( counter = 0; counter < SIZE; counter++ ) 22 printf( "%5d", a[ counter ] ); 23 24 if ( order == 1 ) { 25 bubble( a, SIZE, &ascending ); 26 printf( "\ndata items in ascending order\n" ); 27 } 28 else { 29 bubble( a, SIZE, &descending ); 30 printf( "\ndata items in descending order\n" ); 31 } 32 Notice the function pointer parameter.

33 for ( counter = 0; counter < SIZE; counter++ ) 34 printf( "%5d", a[ counter ] ); 35 36 printf( "\n" ); 37 38 return 0; 39 } 40 41 void bubble( int work[], const int size, 42 int (*compare)( int, int ) ) 43 { 44 int pass, count; 45 46 void swap( int *, int * ); 47 48 for ( pass = 1; pass < size; pass++ ) 49 50 for ( count = 0; count < size - 1; count++ ) 51 52 if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 53 swap( &work[ count ], &work[ count + 1 ] ); 54 } 55 56 void swap( int *element1ptr, int *element2ptr ) 57 { 58 int temp; 59 60 temp = *element1ptr; 61 *element1ptr = *element2ptr; 62 *element2ptr = temp; 63 } 64 ascending and descending return true or false. bubble calls swap if the function call returns true. Notice how function pointers are called using the dereferencing operator. The * is not required, but emphasizes that compare is a function pointer and not a function.

65 int ascending( int a, int b ) 66 { 67 return b < a; /* swap if b is less than a */ 68 } 69 70 int descending( int a, int b ) 71 { 72 return b > a; /* swap if b is greater than a */ 73 } 73 } Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89 Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in descending order 89 68 45 37 12 10 8 6 4 2