Διαφήμιση
Είτε το συνειδητοποιείτε είτε όχι, η συντριπτική πλειονότητα των προγραμμάτων που έχετε χρησιμοποιήσει κάνει χρήση σημείων με κάποιο τρόπο. Ίσως έχετε βιώσει ένα NullPointerException σε κάποιο σημείο. Ως προγραμματιστής, ο κώδικας που γράφετε θα χρησιμοποιήσει κατά πάσα πιθανότητα δείκτες, ακόμα κι αν δεν τους έχετε εφαρμόσει μόνοι σας.
Σήμερα θα σας δείξω πώς λειτουργούν οι δείκτες, οπότε ίσως θέλετε να δείτε πώς λειτουργούν οι πίνακες και οι λίστες Πώς λειτουργούν οι πίνακες και οι λίστες στο PythonΟι πίνακες και οι λίστες είναι μερικές από τις πιο χρήσιμες δομές δεδομένων στον προγραμματισμό - αν και λίγοι άνθρωποι τις χρησιμοποιούν στο μέγιστο των δυνατοτήτων τους. Διαβάστε περισσότερα για ένα πρόγραμμα εκκίνησης προγραμματισμού. Αυτό το άρθρο θα βασίζεται περισσότερο στη θεωρία από το συνηθισμένο, αλλά εμμείνουμε σε αυτό, οι δείκτες είναι πολύ περίπλοκοι!
Σύνταξη κώδικα
Πριν ανακαλύψετε δείκτες, πρέπει να καταλάβετε πώς δημιουργείται και εκτελείται ο κώδικας - ίσως το γνωρίζετε ήδη. Αυτή η ενότητα θα έχει αρκετά γενικές δηλώσεις - πράγματα που ισχύουν για το
η πλειοψηφία γλωσσών, αλλά όχι απαραίτητα όλες.Ας επαναφέρουμε τα πράγματα στην αρχή. Κάθε υπολογιστής χρησιμοποιεί δυαδικό Τι είναι το δυαδικό; [Η τεχνολογία εξηγείται]Δεδομένου ότι το δυαδικό είναι τόσο απολύτως θεμελιώδες για την ύπαρξη υπολογιστών, φαίνεται περίεργο που δεν έχουμε αντιμετωπίσει ποτέ το θέμα πριν - έτσι σήμερα σκέφτηκα ότι θα έδινα μια σύντομη επισκόπηση του τι δυαδικό ... Διαβάστε περισσότερα , μια σειρά από μηδενικά και μηδενικά που αποτελούν τη σύγχρονη τεχνολογία όπως τη γνωρίζουμε. Είναι εξαιρετικά δύσκολο να κωδικοποιήσετε οτιδήποτε σε δυαδικό (τα αρχεία θα ήταν πολύ μπερδεμένα), καθώς αυτές είναι οι πρώτες οδηγίες που χρειάζεστε από εσάς κεντρική μονάδα επεξεργασίας ή CPU για λειτουργία Τι είναι μια CPU και τι κάνει;Τα υπολογιστικά ακρωνύμια προκαλούν σύγχυση. Τι είναι η CPU ούτως ή άλλως; Και χρειάζομαι επεξεργαστή τετραπλού ή διπλού πυρήνα; Τι γίνεται με την AMD ή την Intel; Είμαστε εδώ για να σας βοηθήσουμε να εξηγήσετε τη διαφορά! Διαβάστε περισσότερα . Αυτό είναι γνωστό ως Κωδικός μηχανήματος.
Το επόμενο βήμα από τον κωδικό του μηχανήματος είναι Συνέλευση. Αυτή είναι μια κάπως ανθρώπινη μορφή αναγνώσιμη. Ενώ είναι ακόμα πολύπλοκο να προγραμματιστεί, είναι δυνατόν. Η συναρμολόγηση αποτελείται από μια σειρά απλών εντολών για την εκτέλεση εργασιών και είναι γνωστή ως χαμηλό επίπεδο γλώσσα προγραμματισμού. Είναι δυνατό να γράψετε σύνθετα προγράμματα, αλλά είναι δύσκολο να εκφράσετε αφηρημένες έννοιες και απαιτεί πολλή προσοχή.
Πολλά βιντεοπαιχνίδια και εφαρμογές υψηλής απόδοσης έχουν κάποια λογική γραμμένη στη συναρμολόγηση, καθώς ορισμένες πραγματικές αυξήσεις ταχύτητας μπορούν να βρεθούν αν γνωρίζετε τι κάνετε. Ωστόσο, για τη συντριπτική πλειονότητα των προγραμμάτων προγραμματισμού, δεν χρειάζεται να γνωρίζετε καθόλου συναρμολόγηση.
Επομένως, εάν ο κώδικας του μηχανήματος είναι πολύ δύσκολο να γραφτεί και η συναρμολόγηση είναι πολύ δύσκολο να προγραμματιστεί, με τι γράφετε τον κώδικα; Εδώ είναι υψηλό επίπεδο έρχονται γλώσσες. Οι γλώσσες υψηλού επιπέδου διευκολύνουν την εγγραφή προγραμμάτων. Μπορείτε να προγραμματίσετε σε κάτι που μοιάζει με τη μητρική σας γλώσσα και είναι εύκολο να εκφράσετε πολύπλοκους αλγόριθμους. Μπορεί να έχετε ακούσει πολλές γλώσσες υψηλού επιπέδου (και σίγουρα θα έχετε χρησιμοποιήσει ένα πρόγραμμα γραμμένο σε αυτές):
- ΒΑΣΙΚΟΣ
- C ++
- Ψελλίζω
Αυτές οι γλώσσες είναι πολύ παλιές τώρα και πολλές αναπτύχθηκαν στις αρχές της δεκαετίας του 1950! Σχεδόν κάθε σύγχρονη γλώσσα προγραμματισμού είναι μια γλώσσα υψηλού επιπέδου, συμπεριλαμβανομένων των PHP και Python. Υπάρχουν περισσότερες γλώσσες που εφευρίσκονται καθημερινά (αν και υπάρχουν πιθανώς αρκετές τώρα), αλλά πώς ακριβώς λειτουργεί ο κώδικάς σας εάν οι υπολογιστές χρειάζονται κώδικα μηχανήματος;
Εδώ έρχεται η συλλογή. Ένας μεταγλωττιστής είναι ένα πρόγραμμα που μετατρέπει τον κώδικα υψηλού επιπέδου σε μια φόρμα που μπορεί να εκτελεστεί. Αυτή θα μπορούσε να είναι μια άλλη γλώσσα υψηλού επιπέδου, αλλά είναι συνήθως συναρμολόγηση. Ορισμένες γλώσσες (όπως Python ή Java) μετατρέπουν τον κώδικά σας σε ένα ενδιάμεσο στάδιο που ονομάζεται bytecode. Αυτό θα χρειαστεί να μεταγλωττιστεί ξανά σε μεταγενέστερη ημερομηνία, η οποία συνήθως γίνεται κατόπιν παραγγελίας, όπως όταν εκτελείται το πρόγραμμα. Αυτό είναι γνωστό ως πάνω στην ώρα συλλογή, και είναι αρκετά δημοφιλές.
Διαχείριση μνήμης
Τώρα που γνωρίζετε πώς λειτουργούν οι γλώσσες προγραμματισμού, ας δούμε τη διαχείριση μνήμης σε γλώσσες υψηλού επιπέδου. Για αυτά τα παραδείγματα, θα χρησιμοποιώ ψευδοκώδικας - κωδικός γραμμένος όχι σε συγκεκριμένη γλώσσα, αλλά χρησιμοποιείται για να δείξει έννοιες αντί για ακριβή σύνταξη. Σήμερα, αυτό μοιάζει κυρίως με το C ++, καθώς είναι η καλύτερη γλώσσα υψηλού επιπέδου (κατά τη γνώμη μου).
Για αυτήν την ενότητα, θα σας βοηθήσει αν έχετε κατανόηση πώς λειτουργεί η RAM Ένας γρήγορος και βρώμικος οδηγός για τη μνήμη RAM: Τι πρέπει να γνωρίζετεΗ μνήμη RAM είναι ένα κρίσιμο στοιχείο κάθε υπολογιστή, αλλά μπορεί να προκαλέσει σύγχυση. Το αναλύουμε με εύχρηστους όρους που θα καταλάβετε. Διαβάστε περισσότερα .
Οι περισσότερες γλώσσες έχουν μεταβλητές - κοντέινερ που αποθηκεύουν ορισμένα δεδομένα. Πρέπει να ορίσετε ρητά τον τύπο δεδομένων. Ορισμένες δυναμικά δακτυλογραφημένες γλώσσες όπως η Python ή η PHP το χειρίζονται για εσάς, αλλά πρέπει ακόμη να το κάνουν.
Ας πούμε ότι έχετε μια μεταβλητή:
int myNumber;
Αυτός ο κωδικός δηλώνει μια μεταβλητή που ονομάζεται ο αριθμός μου, και του δίνει έναν τύπο δεδομένων του ακέραιος αριθμός. Μόλις μεταγλωττιστεί, ο υπολογιστής ερμηνεύει αυτήν την εντολή ως:
"Βρείτε κάποια κενή μνήμη και κρατήστε χώρο αρκετά μεγάλο για να αποθηκεύσετε έναν ακέραιο"
Μόλις εκτελεστεί αυτή η εντολή, αυτό το κομμάτι μνήμης δεν μπορεί να χρησιμοποιηθεί από άλλο πρόγραμμα. Δεν περιέχει ακόμη δεδομένα, αλλά προορίζεται για τη μεταβλητή myNumber.
Τώρα εκχωρήστε μια τιμή στη μεταβλητή σας:
myNumber = 10;
Για να ολοκληρώσετε αυτήν την εργασία, ο υπολογιστής σας έχει πρόσβαση στην δεσμευμένη θέση μνήμης και αλλάζει όποια τιμή αποθηκεύεται εκεί, σε αυτήν τη νέα τιμή.
Τώρα, όλα αυτά είναι καλά και καλά, αλλά πώς οι θέσεις μνήμης δεν διατηρούνται; Εάν τα προγράμματα διατηρούσαν όλη τη μνήμη που τους αρέσει, η μνήμη RAM θα γεμίσει αμέσως - αυτό θα έκανε για ένα πολύ αργό σύστημα.
Για να αποφευχθεί αυτό το πιθανό ζήτημα, πολλές γλώσσες εφαρμόζουν ένα συλλέκτης σκουπιδιών, χρησιμοποιείται για την καταστροφή μεταβλητών (και συνεπώς απελευθέρωσης των δεσμευμένων θέσεων μνήμης) που έχουν φύγει εκτός του πεδίου εφαρμογής.
Ίσως αναρωτιέστε ποιο είναι το πεδίο εφαρμογής και γιατί είναι τόσο σημαντικό. Το πεδίο εφαρμογής καθορίζει τα όρια και τη διάρκεια ζωής των μεταβλητών ή οποιαδήποτε μνήμη που χρησιμοποιείται από ένα πρόγραμμα. Μια μεταβλητή είναι "εκτός εμβέλειας" όταν δεν είναι πλέον προσβάσιμη από οποιονδήποτε κωδικό (δηλαδή όταν μπαίνει ο συλλέκτης απορριμμάτων). Ακολουθεί ένα παράδειγμα:
μαθηματικά συνάρτησης () {int firstNumber = 1; } int secondNumber = 2; εκτύπωση (firstNumber + secondNumber); // δεν θα δουλέψει
Αυτό το παράδειγμα δεν θα μεταγλωττιστεί. Η μεταβλητή πρώτος αριθμός είναι εντός του μαθηματικά λειτουργία, έτσι αυτό είναι το πεδίο εφαρμογής. Δεν είναι δυνατή η πρόσβαση από έξω από τη λειτουργία στην οποία έχει δηλωθεί. Αυτή είναι μια σημαντική ιδέα προγραμματισμούκαι η κατανόηση είναι ζωτικής σημασίας για τη συνεργασία με δείκτες.
Αυτός ο τρόπος χειρισμού της μνήμης ονομάζεται σωρός. Είναι ο τρόπος που λειτουργεί η συντριπτική πλειονότητα των προγραμμάτων. Δεν χρειάζεται να καταλάβετε τους δείκτες για να το χρησιμοποιήσετε και είναι αρκετά καλά δομημένο. Το μειονέκτημα της στοίβας είναι η ταχύτητα. Καθώς ο υπολογιστής πρέπει να εκχωρήσει μνήμη, να παρακολουθεί τις μεταβλητές και να εκτελεί τη συλλογή απορριμμάτων, υπάρχει μια μικρή επιβάρυνση. Αυτό είναι καλό για μικρότερα προγράμματα, αλλά τι γίνεται με εργασίες υψηλής απόδοσης ή για εφαρμογές με βαριά δεδομένα;
Εισαγάγετε: δείκτες.
Δείκτες
Στην επιφάνεια, οι δείκτες ακούγονται απλοί. Αναφέρουν (δείχνω) μια θέση στη μνήμη. Αυτό μπορεί να μην φαίνεται διαφορετικό από τις «κανονικές» μεταβλητές στη στοίβα, αλλά πιστέψτε με, υπάρχει μια τεράστια διαφορά. Οι δείκτες αποθηκεύονται στο σωρός. Αυτό είναι το αντίθετο του stack - είναι λιγότερο οργανωμένο, αλλά είναι πολύ πιο γρήγορο.
Ας δούμε πώς εκχωρούνται μεταβλητές στη στοίβα:
int numberOne = 1; int numberTwo = numberOne;
Αυτή είναι απλή σύνταξη. Η μεταβλητή νούμερο δύο περιέχει το νούμερο ένα. Η τιμή αντιγράφεται κατά τη διάρκεια της ανάθεσης από το νούμερο ένα μεταβλητός.
Εάν θέλετε να πάρετε το διεύθυνση μνήμης μιας μεταβλητής, αντί για την τιμή της, πρέπει να χρησιμοποιήσετε το σύμβολο ampersand (&). Αυτό ονομάζεται το διεύθυνση του χειριστή και αποτελεί ουσιαστικό μέρος της εργαλειοθήκης δείκτη.
int numberOne = 1; int numberTwo = & numberOne;
Τώρα το νούμερο δύο μεταβλητός πόντους σε μια τοποθεσία μνήμης, αντί να αντιγράφεται ο νούμερο ένα στη δική της, νέα θέση μνήμης. Εάν επρόκειτο να εξάγετε αυτήν τη μεταβλητή, δεν θα ήταν το νούμερο ένα (παρόλο που είναι αποθηκευμένο στη θέση μνήμης). Θα έδινε τη θέση της μνήμης (πιθανώς κάτι σαν το 2167, αν και διαφέρει ανάλογα με το σύστημα και τη διαθέσιμη μνήμη RAM). Για να αποκτήσετε πρόσβαση στην τιμή που είναι αποθηκευμένη σε ένα δείκτη, αντί για τη θέση της μνήμης, πρέπει να υποτίμηση ο δείκτης. Αυτό έχει άμεση πρόσβαση στην τιμή, που θα είναι το νούμερο ένα σε αυτήν την περίπτωση. Δείτε πώς αποπροσανατολίζετε έναν δείκτη:
int numberTwo = * numberOne;
ο χειριστής διαφωνίας είναι ένας αστερίσκος (*).
Αυτό μπορεί να είναι μια δύσκολη ιδέα για κατανόηση, οπότε ας το ξαναπάμε:
- ο διεύθυνση του ο τελεστής (&) αποθηκεύει τη διεύθυνση μνήμης.
- ο χειριστής διαφωνίας (*) έχει πρόσβαση στην τιμή.
Η σύνταξη αλλάζει ελαφρώς όταν δηλώνετε δείκτες:
int * myPointer;
Ο τύπος δεδομένων του int εδώ αναφέρεται στον τύπο δεδομένων ο δείκτης πόντους και όχι τον τύπο του ίδιου του δείκτη.
Τώρα που ξέρετε τι είναι οι δείκτες, μπορείτε να κάνετε μερικά πολύ τακτοποιημένα κόλπα μαζί τους! Όταν χρησιμοποιείται μνήμη, ξεκινά το λειτουργικό σας σύστημα διαδοχικά. Μπορείτε να σκεφτείτε τη RAM ως τρύπες περιστεριών. Πολλές τρύπες για να αποθηκεύσετε κάτι, μόνο μία μπορεί να χρησιμοποιηθεί ταυτόχρονα. Η διαφορά εδώ είναι ότι όλες αυτές οι τρύπες περιστεριών είναι αριθμημένες. Κατά την εκχώρηση μνήμης, το λειτουργικό σας σύστημα ξεκινά από τον χαμηλότερο αριθμό και λειτουργεί. Δεν θα περάσει ποτέ μεταξύ τυχαίων αριθμών.
Όταν εργάζεστε με δείκτες, εάν έχετε εκχωρήσει έναν πίνακα, μπορείτε εύκολα να πλοηγηθείτε στο επόμενο στοιχείο με απλή αύξηση του δείκτη σας.
Εδώ είναι ενδιαφέρον. Όταν μεταβιβάζετε τιμές σε μια συνάρτηση (χρησιμοποιώντας μεταβλητές που είναι αποθηκευμένες στη στοίβα), αυτές οι τιμές αντιγράφονται στη λειτουργία σας. Εάν πρόκειται για μεγάλες μεταβλητές, το πρόγραμμα σας τις αποθηκεύει δύο φορές. Όταν ολοκληρωθεί η λειτουργία σας, μπορεί να χρειαστείτε έναν τρόπο για να επιστρέψετε αυτές τις τιμές. Οι συναρτήσεις μπορούν γενικά να επιστρέψουν μόνο ένα πράγμα - τι γίνεται αν θέλετε να επιστρέψετε δύο, τρία ή τέσσερα πράγματα;
Εάν μεταβιβάσετε έναν δείκτη στη λειτουργία σας, αντιγράφεται μόνο η διεύθυνση μνήμης (η οποία είναι μικρή). Αυτό εξοικονομεί CPU σας πολλή δουλειά! Ίσως ο δείκτης σας δείχνει μια τεράστια συστοιχία εικόνων - όχι μόνο η λειτουργία σας μπορεί να λειτουργήσει ακριβώς με το ίδιο δεδομένα που είναι αποθηκευμένα στην ίδια ακριβώς θέση μνήμης, αλλά μόλις ολοκληρωθεί, δεν χρειάζεται να επιστρέψετε Οτιδήποτε. Καθαρός!
Πρέπει όμως να είστε πολύ προσεκτικοί. Οι δείκτες εξακολουθούν να είναι εκτός εμβέλειας και να συλλέγονται από τον συλλέκτη απορριμμάτων. Ωστόσο, οι τιμές που είναι αποθηκευμένες στη μνήμη δεν συλλέγονται. Αυτό ονομάζεται διαρροή μνήμης. Δεν μπορείτε πλέον να έχετε πρόσβαση στα δεδομένα (καθώς οι δείκτες έχουν καταστραφεί), αλλά εξακολουθεί να εξαντλεί τη μνήμη. Αυτός είναι ένας κοινός λόγος για πολλά προγράμματα να καταρρέουν και μπορεί να αποτύχει θεαματικά εάν υπάρχει μεγάλη ποσότητα δεδομένων. Τις περισσότερες φορές, το λειτουργικό σας σύστημα θα σκοτώσει το πρόγραμμά σας εάν έχετε μεγάλη διαρροή (χρησιμοποιώντας περισσότερη μνήμη RAM από το σύστημα), αλλά αυτό δεν είναι επιθυμητό.
Οι δείκτες εντοπισμού σφαλμάτων μπορεί να είναι ένας εφιάλτης, ειδικά εάν εργάζεστε με μεγάλες ποσότητες δεδομένων ή εργάζεστε σε βρόχους. Τα μειονεκτήματά τους και η δυσκολία στην κατανόησή τους αξίζουν πραγματικά τις ανταλλαγές που κερδίζετε στην απόδοση. Αν και θυμηθείτε, μπορεί να μην απαιτούνται πάντα.
Αυτό είναι για σήμερα. Ελπίζω να έχετε μάθει κάτι χρήσιμο για ένα περίπλοκο θέμα. Φυσικά, δεν έχουμε καλύψει όλα όσα πρέπει να γνωρίζουμε - είναι ένα πολύ περίπλοκο θέμα. Αν σας ενδιαφέρει να μάθετε περισσότερα, σας συνιστώ ανεπιφύλακτα C ++ σε 24 ώρες.
Εάν αυτό ήταν λίγο περίπλοκο, ρίξτε μια ματιά ο οδηγός μας για τις ευκολότερες γλώσσες προγραμματισμού 6 ευκολότερες γλώσσες προγραμματισμού για μάθηση για αρχάριουςΗ εκμάθηση του προγράμματος είναι η εύρεση της σωστής γλώσσας όπως και η διαδικασία επιμόρφωσης. Εδώ είναι οι κορυφαίες έξι ευκολότερες γλώσσες προγραμματισμού για αρχάριους. Διαβάστε περισσότερα .
Μάθατε πώς λειτουργούν οι δείκτες σήμερα; Έχετε κάποιες συμβουλές και κόλπα που θέλετε να μοιραστείτε με άλλους προγραμματιστές; Μεταβείτε στα σχόλια και μοιραστείτε τις σκέψεις σας παρακάτω!
Ο Joe είναι απόφοιτος της Επιστήμης Υπολογιστών από το Πανεπιστήμιο του Λίνκολν του Ηνωμένου Βασιλείου. Είναι επαγγελματίας προγραμματιστής λογισμικού και όταν δεν πετάει drones ή γράφει μουσική, μπορεί συχνά να βρεθεί να φωτογραφίζει ή να δημιουργεί βίντεο.