Τι είναι ο δείκτης στο C;
Ο δείκτης σε C, είναι μια μεταβλητή που αποθηκεύει τη διεύθυνση μιας άλλης μεταβλητής. Ένας δείκτης μπορεί επίσης να χρησιμοποιηθεί για αναφορά σε μια άλλη λειτουργία δείκτη. Ένας δείκτης μπορεί να αυξηθεί / μειωθεί, δηλαδή να δείξει στην επόμενη / προηγούμενη θέση μνήμης. Ο σκοπός του δείκτη είναι να εξοικονομήσετε χώρο μνήμης και να επιτύχετε γρηγορότερο χρόνο εκτέλεσης.
Πώς να χρησιμοποιήσετε δείκτες σε C
Εάν δηλώσουμε μια μεταβλητή v του τύπου int, το v θα αποθηκεύσει πραγματικά μια τιμή.
Το v είναι ίσο με το μηδέν τώρα.
Ωστόσο, κάθε μεταβλητή, εκτός από την τιμή, έχει επίσης τη διεύθυνσή της (ή, απλά, όπου βρίσκεται στη μνήμη). Η διεύθυνση μπορεί να ανακτηθεί τοποθετώντας ένα σύμβολο (&) πριν από το όνομα της μεταβλητής.
Εάν εκτυπώσετε τη διεύθυνση μιας μεταβλητής στην οθόνη, θα μοιάζει με εντελώς τυχαίος αριθμός (επιπλέον, μπορεί να διαφέρει από εκτέλεση σε εκτέλεση).
Ας το δοκιμάσουμε στην πράξη με δείκτη στο παράδειγμα Γ
Η έξοδος αυτού του προγράμματος είναι -480613588.
Τώρα, τι είναι ένας δείκτης; Αντί να αποθηκεύει μια τιμή, ένας δείκτης θα αποθηκεύει τη διεύθυνση μιας μεταβλητής.
Μεταβλητή δείκτη
Int * y = & v;
ΜΕΤΑΒΛΗΤΟΣ |
ΔΕΙΚΤΗΣ |
Μια τιμή αποθηκευμένη σε μια ονομαστική διεύθυνση αποθήκευσης / μνήμης |
Μια μεταβλητή που δείχνει τη διεύθυνση αποθήκευσης / μνήμης μιας άλλης μεταβλητής |
Δήλωση ενός δείκτη
Όπως οι μεταβλητές, οι δείκτες στον προγραμματισμό C πρέπει να δηλώνονται προτού μπορέσουν να χρησιμοποιηθούν στο πρόγραμμά σας. Οι δείκτες μπορούν να ονομάζονται οτιδήποτε θέλετε, εφόσον τηρούν τους κανόνες ονομασίας του C. Μια δήλωση δείκτη έχει την ακόλουθη μορφή.
data_type * pointer_variable_name;
Εδώ,
- data_type είναι ο βασικός τύπος του δείκτη των μεταβλητών τύπων του C και δείχνει τον τύπο της μεταβλητής στην οποία δείχνει ο δείκτης.
- Ο αστερίσκος (*: ο ίδιος αστερίσκος που χρησιμοποιείται για πολλαπλασιασμό) που είναι χειριστής έμμεσης, δηλώνει έναν δείκτη.
Ας δούμε μερικές έγκυρες δηλώσεις δείκτη σε αυτό το σεμινάριο δείκτη C:
int *ptr_thing; /* pointer to an integer */int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */double *ptr2; /* pointer to a double */float *ptr3; /* pointer to a float */char *ch1 ; /* pointer to a character */float *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */
Αρχικοποιήστε έναν δείκτη
Αφού δηλώσουμε έναν δείκτη, το αρχικοποιούμε σαν τυπικές μεταβλητές με μια μεταβλητή διεύθυνση. Εάν οι δείκτες στον προγραμματισμό C δεν είναι αρχικοποιημένοι και δεν χρησιμοποιούνται στο πρόγραμμα, τα αποτελέσματα είναι απρόβλεπτα και δυνητικά καταστροφικά.
Για να λάβουμε τη διεύθυνση μιας μεταβλητής, χρησιμοποιούμε τον τελεστή ampersand (&), που τοποθετείται πριν από το όνομα μιας μεταβλητής της οποίας τη διεύθυνση χρειαζόμαστε. Η αρχικοποίηση του δείκτη γίνεται με την ακόλουθη σύνταξη.
Σύνταξη δείκτη
pointer = &variable;
Ένα απλό πρόγραμμα για απεικόνιση δείκτη δίνεται παρακάτω:
#includeint main(){int a=10; //variable declarationint *p; //pointer variable declarationp=&a; //store address of variable a in pointer pprintf("Address stored in a variable p is:%x\n",p); //accessing the addressprintf("Value stored in a variable p is:%d\n",*p); //accessing the valuereturn 0;}
Παραγωγή:
Address stored in a variable p is:60ff08Value stored in a variable p is:10
Χειριστής | Εννοια |
* | Εξυπηρετεί 2 σκοπούς
|
& | Εξυπηρετεί μόνο 1 σκοπό
|
Τύποι δεικτών σε C
Ακολουθούν οι διαφορετικοί τύποι δεικτών στο C :
Null Pointer
Μπορούμε να δημιουργήσουμε ένα μηδενικό δείκτη, εκχωρώντας μηδενική τιμή κατά τη δήλωση δείκτη. Αυτή η μέθοδος είναι χρήσιμη όταν δεν έχετε εκχωρήσει καμία διεύθυνση στο δείκτη. Ένας μηδενικός δείκτης περιέχει πάντα την τιμή 0.
Το ακόλουθο πρόγραμμα απεικονίζει τη χρήση ενός μηδενικού δείκτη:
#includeint main(){int *p = NULL; //null pointerprintf(“The value inside variable p is:\n%x”,p);return 0;}
Παραγωγή:
The value inside variable p is:0
Κενός δείκτης
Στον προγραμματισμό C, ένας κενός δείκτης καλείται επίσης ως γενικός δείκτης. Δεν έχει τυπικό τύπο δεδομένων. Ένας κενός δείκτης δημιουργείται χρησιμοποιώντας τη λέξη-κλειδί κενό. Μπορεί να χρησιμοποιηθεί για την αποθήκευση μιας διεύθυνσης οποιασδήποτε μεταβλητής.
Το ακόλουθο πρόγραμμα απεικονίζει τη χρήση ενός κενού δείκτη:
#includeint main(){void *p = NULL; //void pointerprintf("The size of pointer is:%d\n",sizeof(p));return 0;}
Παραγωγή:
The size of pointer is:4
Άγριος δείκτης
Ένας δείκτης λέγεται ότι είναι ένας άγριος δείκτης εάν δεν αρχικοποιείται σε τίποτα. Αυτοί οι τύποι δεικτών C δεν είναι αποδοτικοί επειδή μπορεί να δείχνουν κάποια άγνωστη θέση μνήμης που μπορεί να προκαλέσει προβλήματα στο πρόγραμμά μας και μπορεί να οδηγήσει σε διακοπή λειτουργίας του προγράμματος. Κάποιος πρέπει πάντα να είναι προσεκτικός ενώ εργάζεστε με άγριους δείκτες.
Το ακόλουθο πρόγραμμα δείχνει τη χρήση του wild pointer:
#includeint main(){int *p; //wild pointerprintf("\n%d",*p);return 0;}
Παραγωγή
timeout: the monitored command dumped coresh: line 1: 95298 Segmentation fault timeout 10s main
Άλλοι τύποι δεικτών στο «c» είναι οι εξής:
- Κουνάμε δείκτη
- Σύνθετος δείκτης
- Κοντά στο δείκτη
- Μακρινός δείκτης
- Τεράστιο δείκτη
Δείκτες άμεσης και έμμεσης πρόσβασης
Στο C, υπάρχουν δύο ισοδύναμοι τρόποι πρόσβασης και χειρισμού ενός μεταβλητού περιεχομένου
- Άμεση πρόσβαση: χρησιμοποιούμε απευθείας το όνομα της μεταβλητής
- Έμμεση πρόσβαση: χρησιμοποιούμε ένα δείκτη στη μεταβλητή
Ας το καταλάβουμε με τη βοήθεια του παρακάτω προγράμματος
#include/* Declare and initialize an int variable */int var = 1;/* Declare a pointer to int */int *ptr;int main( void ){/* Initialize ptr to point to var */ptr = &var;/* Access var directly and indirectly */printf("\nDirect access, var = %d", var);printf("\nIndirect access, var = %d", *ptr);/* Display the address of var two ways */printf("\n\nThe address of var = %d", &var);printf("\nThe address of var = %d\n", ptr);/*change the content of var through the pointer*/*ptr=48;printf("\nIndirect access, var = %d", *ptr);return 0;}
Μετά την κατάρτιση του προγράμματος χωρίς σφάλματα, το αποτέλεσμα είναι:
Direct access, var = 1Indirect access, var = 1The address of var = 4202496The address of var = 4202496Indirect access, var = 48
Δείκτης αριθμητικών σε C
Οι λειτουργίες δείκτη συνοψίζονται στο ακόλουθο σχήμα
Λειτουργία προτεραιότητας (προτεραιότητα)
Όταν δουλεύουμε με δείκτες C, πρέπει να τηρούμε τους ακόλουθους κανόνες προτεραιότητας:
- Οι τελεστές * και έχουν την ίδια προτεραιότητα με τους unary τελεστές (η άρνηση !, η αύξηση ++, μείωση--).
- Στην ίδια έκφραση, οι unary τελεστές *, &,!, ++, - αξιολογούνται από δεξιά προς τα αριστερά.
Εάν ένας δείκτης P δείχνει μια μεταβλητή X, τότε * P μπορεί να χρησιμοποιηθεί όπου μπορεί να γραφτεί το X.
Οι ακόλουθες εκφράσεις είναι ισοδύναμες:
int X = 10 int * P = & Υ; Για τον παραπάνω κώδικα, ισχύουν οι παρακάτω εκφράσεις | |
Εκφραση | Ισοδύναμη έκφραση |
Y = * P + 1 * P = * P + 10 * P + = 2 ++ * P (* P) ++ | Y = X + 1 X = X + 10 X + = 2 ++ X X ++ |
Στην τελευταία περίπτωση, χρειάζονται παρενθέσεις: καθώς οι unary τελεστές * και ++ αξιολογούνται από δεξιά προς τα αριστερά, χωρίς τις παρενθέσεις ο δείκτης P θα αυξηθεί, όχι το αντικείμενο στο οποίο δείχνει το P.
Στον παρακάτω πίνακα παρουσιάζεται η αριθμητική και βασική λειτουργία που μπορούν να χρησιμοποιηθούν όταν ασχολούνται με δείκτες C
Λειτουργία | Εξήγηση |
ΑΝΑΘΕΣΗ ΕΡΓΑΣΙΑΣ | int * P1, * P2 P1 = P2; Τα P1 και P2 δείχνουν την ίδια ακέραια μεταβλητή |
Αύξηση και μείωση | Int * P1; P1 ++; P1--; |
Προσθήκη όφσετ (Σταθερό) | Αυτό επιτρέπει στον δείκτη να μετακινεί στοιχεία N σε έναν πίνακα. Ο δείκτης θα αυξηθεί ή να μειωθεί κατά Ν φορές τον αριθμό των byte (ες) του τύπου της μεταβλητής. P1 + 5; |
C Δείκτες & πίνακες με παραδείγματα
Παραδοσιακά, έχουμε πρόσβαση στα στοιχεία του πίνακα χρησιμοποιώντας το ευρετήριό του, αλλά αυτή η μέθοδος μπορεί να εξαλειφθεί χρησιμοποιώντας δείκτες. Οι δείκτες διευκολύνουν την πρόσβαση σε κάθε στοιχείο πίνακα.
#includeint main(){int a[5]={1,2,3,4,5}; //array initializationint *p; //pointer declaration/*the ptr points to the first element of the array*/p=a; /*We can also type simply ptr==&a[0] */printf("Printing the array elements using pointer\n");for(int i=0;i<5;i++) //loop for traversing array elements{printf("\n%x",*p); //printing array elementsp++; //incrementing to the next element, you can also write p=p+1}return 0;}
Παραγωγή
12345
Η προσθήκη ενός συγκεκριμένου αριθμού σε ένα δείκτη θα μετακινήσει τη θέση του δείκτη στην τιμή που λαμβάνεται από μια λειτουργία προσθήκης. Ας υποθέσουμε ότι το p είναι ένας δείκτης που δείχνει προς το παρόν τη θέση μνήμης 0 εάν εκτελέσουμε μετά τη λειτουργία προσθήκης, p + 1 τότε θα εκτελεστεί με αυτόν τον τρόπο:
Δεδομένου ότι το p δείχνει προς το παρόν τη θέση 0 μετά την προσθήκη 1, η τιμή θα γίνει 1, και ως εκ τούτου ο δείκτης θα δείχνει στη θέση μνήμης 1.
C Δείκτες και χορδές με παραδείγματα
Μια συμβολοσειρά είναι ένας πίνακας αντικειμένων char, που τελειώνει με έναν μηδενικό χαρακτήρα «\ 0». Μπορούμε να χειριστούμε χορδές χρησιμοποιώντας δείκτες. Αυτός ο δείκτης στο παράδειγμα Γ εξηγεί αυτήν την ενότητα
#include#include int main(){char str[]="Hello Guru99!";char *p;p=str;printf("First character is:%c\n",*p);p =p+1;printf("Next character is:%c\n",*p);printf("Printing all the characters in a string\n");p=str; //reset the pointerfor(int i=0;i Παραγωγή
First character is:HNext character is:ePrinting all the characters in a stringHelloGuru99!Ένας άλλος τρόπος αντιμετώπισης χορδών είναι με μια σειρά από δείκτες όπως στο ακόλουθο πρόγραμμα:
#includeint main(){char *materials[ ] = { "iron", "copper", "gold"};printf("Please remember these materials :\n");int i ;for (i = 0; i < 3; i++) {printf("%s\n", materials[ i ]);}return 0;} Παραγωγή:
Please remember these materials:ironcoppergoldΠλεονεκτήματα των δεικτών σε C
- Οι δείκτες είναι χρήσιμοι για πρόσβαση σε θέσεις μνήμης.
- Οι δείκτες παρέχουν έναν αποτελεσματικό τρόπο πρόσβασης στα στοιχεία μιας δομής πίνακα.
- Οι δείκτες χρησιμοποιούνται για δυναμική κατανομή μνήμης καθώς και για την αφαίρεση θέσεων.
- Οι δείκτες χρησιμοποιούνται για να σχηματίσουν σύνθετες δομές δεδομένων όπως συνδεδεμένη λίστα, γράφημα, δέντρο κ.λπ.
Μειονεκτήματα των δεικτών στο Γ
- Οι δείκτες είναι λίγο περίπλοκοι να καταλάβουν.
- Οι δείκτες μπορούν να οδηγήσουν σε διάφορα σφάλματα, όπως σφάλματα τμηματοποίησης ή να έχουν πρόσβαση σε μια θέση μνήμης που δεν απαιτείται καθόλου.
- Εάν παρέχεται λανθασμένη τιμή σε ένα δείκτη, ενδέχεται να προκαλέσει καταστροφή της μνήμης.
- Οι δείκτες είναι επίσης υπεύθυνοι για τη διαρροή μνήμης.
- Οι δείκτες είναι συγκριτικά πιο αργοί από αυτόν των μεταβλητών.
- Οι προγραμματιστές δυσκολεύονται να συνεργαστούν με τους δείκτες. Επομένως, είναι ευθύνη του προγραμματιστή να χειρίζεται προσεκτικά έναν δείκτη.
Περίληψη
- Ο δείκτης δεν είναι παρά μια θέση μνήμης όπου αποθηκεύονται τα δεδομένα.
- Ένας δείκτης χρησιμοποιείται για πρόσβαση στη θέση μνήμης.
- Υπάρχουν διάφοροι τύποι δεικτών, όπως ένας μηδενικός δείκτης, ένας άγριος δείκτης, ένας άδειος δείκτης και άλλοι τύποι δεικτών.
- Οι δείκτες μπορούν να χρησιμοποιηθούν με συστοιχία και συμβολοσειρά για πιο αποτελεσματική πρόσβαση σε στοιχεία.
- Μπορούμε να δημιουργήσουμε δείκτες λειτουργίας για να επικαλεστούμε μια λειτουργία δυναμικά.
- Οι αριθμητικές λειτουργίες μπορούν να γίνουν σε έναν δείκτη που είναι γνωστός ως αριθμητικός δείκτης.
- Οι δείκτες μπορούν επίσης να δείχνουν τη λειτουργία που διευκολύνει την κλήση διαφορετικών λειτουργιών στην περίπτωση καθορισμού μιας σειράς δεικτών.
- Όταν θέλετε να αντιμετωπίσετε διαφορετικούς τύπους μεταβλητών δεδομένων, μπορείτε να χρησιμοποιήσετε έναν δείκτη κενού τύπου πρόβλεψης.