[Powered by Google Translate] [Ενότητα 4 - Άνετα Περισσότερα] [Rob Bowden - Πανεπιστήμιο του Χάρβαρντ] [Αυτό είναι CS50. - CS50.TV] Έχουμε ένα κουίζ αύριο, σε περίπτωση που εσείς δεν το γνωρίζουν αυτό. Είναι βασικά για ό, τι θα μπορούσε να δει σε τάξη ή θα πρέπει να έχουν δει στην τάξη. Αυτό περιλαμβάνει δείκτες, ακόμη κι αν είναι ένα πολύ πρόσφατο θέμα. Θα πρέπει τουλάχιστον να καταλάβουν τα υψηλά επίπεδα τους. Οτιδήποτε που είχε φύγει πάνω στην τάξη θα πρέπει να καταλάβετε για το κουίζ. Έτσι, εάν έχετε ερωτήσεις σχετικά με αυτούς, μπορείτε να τους ρωτήσετε τώρα. Αλλά αυτό πρόκειται να είναι μια πολύ φοιτητής υπό την ηγεσία της συνόδου, όπου εσείς ερωτήσεις, έτσι ελπίζουμε ότι οι άνθρωποι έχουν ερωτήσεις. Υπάρχει κάποιος που έχει ερωτήσεις; Ναι. >> [Φοιτητής] Μπορείς να πάει πέρα ​​από δείκτες πάλι; Θα πάω πάνω από δείκτες. Όλες οι μεταβλητές σας κατ 'ανάγκην ζουν στη μνήμη, αλλά συνήθως δεν ανησυχούν γι 'αυτό και το μόνο που λένε x + 2 και y + 3 και ο compiler θα καταλάβω όπου τα πράγματα είναι ζωντανά για εσάς. Όταν έχουμε να κάνουμε με δείκτες, τώρα που χρησιμοποιείτε ρητά αυτές τις διευθύνσεις μνήμης. Έτσι, μια μεταβλητή θα ζήσουν ποτέ σε μια μοναδική διεύθυνση σε κάθε δεδομένη στιγμή. Αν θέλουμε να δηλώνουμε έναν pointer, τι είναι ο τύπος πρόκειται να μοιάσει; Θέλω να κηρύξει σ δείκτη. Τι κάνει ο τύπος μοιάζει; [Φοιτητής] int * p. Ναι >>. Έτσι, int * p. Και πώς μπορώ να κάνω το σημείο στο x; >> [Φοιτητής] Ampersand. [Bowden] Έτσι, εμπορικό και κυριολεκτικά ονομάζεται η διεύθυνση του επιχειρηματία. Έτσι, όταν λέω & x είναι να πάρει τη διεύθυνση μνήμης της μεταβλητής x. Έτσι, τώρα έχω το δείκτη p, και οπουδήποτε στον κώδικά μου μπορώ να χρησιμοποιήσω * p ή θα μπορούσα να χρησιμοποιήσω x και θα είναι ακριβώς το ίδιο πράγμα. (* Ρ). Τι κάνει αυτό; Τι σημαίνει ότι το αστέρι; [Φοιτητής] Αυτό σημαίνει ότι μια τιμή σε αυτό το σημείο. Ναι >>. Έτσι, αν το δούμε, μπορεί να είναι πολύ χρήσιμο να σκιαγραφήσει τα διαγράμματα όπου αυτό είναι ένα μικρό κουτί μνήμης για χ, η οποία συμβαίνει να έχει την τιμή 4, τότε έχουμε ένα μικρό κουτί της μνήμης για το p, και έτσι να σ. σημεία x, έτσι ώστε να σχεδιάσετε ένα βέλος από το p στο x. Έτσι, όταν λέμε * σ. λέμε πάμε στο κουτί που είναι p. Αστέρια είναι να ακολουθήσετε το βέλος και στη συνέχεια, κάντε ό, τι θέλετε με αυτό το κουτί εκεί. Έτσι μπορώ να πω * p = 7? Και ότι θα πάει στο κουτί που είναι x και η αλλαγή που έως 7. Ή θα μπορούσα να πω int z = * p * 2? Αυτό είναι σύγχυση, επειδή αυτό είναι αστέρι, αστέρι. Το ένα άστρο εύρεση τιμών p, το άλλο αστέρι πολλαπλασιάζεται επί 2. Παρατηρήστε θα μπορούσε να έχει εξίσου καλά αντικατέστησε το p * με x. Μπορείτε να τα χρησιμοποιήσετε με τον ίδιο τρόπο. Και τότε αργότερα μπορώ να έχω σημείο p σε ένα εντελώς νέο πράγμα. Μπορώ μόνο να πω p = &z; Έτσι p τώρα δεν είναι πλέον σημεία για x? Αυτό δείχνει z. Και κάθε φορά που κάνω * p είναι το ίδιο όπως κάνει z. Έτσι, το χρήσιμο πράγμα για αυτό είναι όταν θα αρχίσουν να πάρει σε λειτουργίες. Είναι το είδος των άχρηστων να δηλώσει ένα δείκτη που δείχνει σε κάτι και τότε είστε απλά εύρεση τιμών όταν θα μπορούσε να χρησιμοποιήσει την αρχική μεταβλητή για να αρχίσει με. Αλλά όταν μπει σε λειτουργία - οπότε ας πούμε ότι έχουμε κάποια λειτουργία, int foo, που παίρνει ένα δείκτη και μόλις κάνει * p = 6? Όπως είδαμε πριν, με swap, δεν μπορείτε να κάνετε μια αποτελεσματική ανταλλαγή και μια ξεχωριστή λειτουργία με απλά περνώντας ακέραιοι, διότι τα πάντα σε C είναι πάντα περνώντας από αξία. Ακόμα και όταν είστε περνώντας δείκτες είστε περνώντας από την αξία. Συμβαίνει ότι αυτές οι αξίες είναι διευθύνσεις μνήμης. Έτσι, όταν λέω foo (ιστ)? Είμαι πέρασμα του δείκτη σε συνάρτηση foo και στη συνέχεια να κάνει foo * p = 6? Έτσι, μέσα από αυτή τη λειτουργία, * p εξακολουθεί να είναι ισοδύναμο προς το x, αλλά δεν μπορώ να χρησιμοποιήσω x στο εσωτερικό αυτής της λειτουργίας, επειδή δεν είναι scoped εντός της εν λόγω λειτουργία. Έτσι * p = 6 είναι ο μόνος τρόπος που μπορώ να αποκτήσετε πρόσβαση σε μια τοπική μεταβλητή από μια άλλη λειτουργία. Ή, επίσης, δείκτες είναι ο μόνος τρόπος που μπορώ να αποκτήσετε πρόσβαση σε μια τοπική μεταβλητή από μια άλλη λειτουργία. [Φοιτητής] Ας πούμε ότι έχετε ήθελε να επιστρέψει ένα δείκτη. Πώς ακριβώς το κάνεις αυτό; [Bowden] Επιστροφή έναν δείκτη όπως σε κάτι σαν int y = 3? Επιστροφή & y; >> [Φοιτητής] Ναι. [Bowden] Εντάξει. Ποτέ δεν θα πρέπει να το κάνετε αυτό. Αυτό είναι κακό. Νομίζω ότι είδα σε αυτές τις διαφάνειες διάλεξης που άρχισε να βλέπει όλο αυτό το διάγραμμα της μνήμης όπου εδώ έχετε τη διεύθυνση μνήμης 0 και κάτω εδώ έχετε μνήμη διεύθυνση 4 συναυλίες ή 2 στο 32. Έτσι λοιπόν έχετε κάποια πράγματα και κάποια πράγματα και στη συνέχεια να έχετε στοίβα σας και έχετε σωρό σας, που μόλις άρχισε να μαθαίνει περίπου, που μεγαλώνει. [Φοιτητής] Δεν είναι ο σωρός πάνω από τη στοίβα; Ναι. Ο σωρός είναι στην κορυφή, έτσι δεν είναι; >> [Φοιτητής] Λοιπόν, έβαλε 0 στην κορυφή. [Φοιτητής] Ω, έβαλε 0 στην κορυφή. >> [Φοιτητής] Ω, εντάξει. Αποποίηση: Οπουδήποτε με CS50 θα πάμε να δούμε αυτό τον τρόπο. >> [Φοιτητής] Εντάξει. Είναι απλά ότι όταν δω τον πρώτο στοίβες, όπως όταν σκέφτεστε από μια στοίβα γνώμη σας για στοίβαγμα τα πράγματα το ένα πάνω στο άλλο. Έτσι, έχουμε την τάση να αναστρέψετε γύρω από αυτό, ώστε η στοίβα μεγαλώνει σαν μια στοίβα κανονικά αντί της στοίβας κρέμεται προς τα κάτω. >> [Φοιτητής] Μην σωρούς τεχνικά μεγαλώσει πάρα πολύ, όμως; Εξαρτάται από το τι εννοείτε με τον όρο μεγαλώνουν. Η στοίβα και σωρού πάντα μεγαλώνουν σε αντίθετες κατευθύνσεις. Μια στοίβα είναι πάντα μεγαλώνουν με την έννοια ότι είναι μεγαλώνουν προς υψηλότερες διευθύνσεις μνήμης, και ο σωρός αυξάνεται κάτω υπό την έννοια ότι μεγαλώνει προς χαμηλότερες διευθύνσεις μνήμης. Έτσι, η κορυφή είναι 0 και το κάτω μέρος είναι υψηλή διευθύνσεις μνήμης. Είναι και οι δύο αυξάνονται, μόνο σε αντίθετες κατευθύνσεις. [Φοιτητής] εννοούσα ακριβώς αυτό, επειδή είπατε βάζετε στοίβα στο κάτω μέρος επειδή φαίνεται πιο διαισθητική επειδή για τη στοίβα για να ξεκινήσει στην κορυφή ενός σωρού, σωρός είναι στην κορυφή του εαυτού πάρα πολύ, έτσι that's - >> Ναι. Μπορείτε επίσης να σκεφτείτε του σωρού, όπως μεγαλώνουν και μεγαλύτερα, αλλά η στοίβα περισσότερο. Έτσι, η στοίβα είναι αυτό που εμείς το είδος της θέλουν να δείξουν μεγαλώνουν. Αλλά παντού εσείς κοιτάζουν αλλιώς θα δείξει διεύθυνση 0 στην κορυφή και η υψηλότερη διεύθυνση μνήμης στο κάτω μέρος, έτσι αυτό είναι συνηθισμένο προβολή της μνήμης. Έχετε μια ερώτηση; [Φοιτητής] Μπορείτε να μας πείτε περισσότερα για το σωρό; Ναι. Θα φτάσουμε σε αυτό σε ένα δευτερόλεπτο. Κατ 'αρχάς, πρόκειται να επιστρέψει πίσω γιατί & y είναι ένα κακό πράγμα, στη στοίβα έχετε μια δέσμη των πλαισίων στοίβας που αντιπροσωπεύουν όλες τις λειτουργίες που έχουν κληθεί. Έτσι, αγνοώντας προηγούμενες πράγματα, η κορυφή της στοίβας σας είναι πάντα θα είναι η κύρια λειτουργία δεδομένου ότι είναι η πρώτη λειτουργία που είναι να ονομάζεται. Και στη συνέχεια, όταν σας καλούν άλλη λειτουργία, η στοίβα θα αυξηθεί προς τα κάτω. Έτσι, αν καλώ κάποια λειτουργία, foo, και παίρνει το δικό του πλαίσιο της στοίβας, μπορεί να καλέσει κάποια λειτουργία, μπαρ? παίρνει το δικό του πλαίσιο στοίβας του. Και γραμμή θα μπορούσε να είναι αναδρομική και θα μπορούσε να ζητήσει η ίδια, και έτσι ώστε δεύτερη κλήση στη γραμμή πρόκειται να πάρει το δικό του πλαίσιο στοίβας του. Και έτσι ό, τι συμβαίνει σε αυτά τα πλαίσια είναι στοίβα όλες τις τοπικές μεταβλητές και όλα τα ορίσματα της συνάρτησης ότι - Οποιαδήποτε πράγματα που είναι τοπικά scoped να πάει αυτή τη λειτουργία σε αυτά τα πλαίσια στοίβα. Έτσι, αυτό σημαίνει ότι όταν είπα κάτι σαν μπαρ είναι μια λειτουργία, Είμαι ακριβώς πρόκειται να δηλώσει έναν ακέραιο αριθμό και στη συνέχεια να επιστρέψει ένα δείκτη σε ακέραιο αυτό. Έτσι, όταν κάνει y ζει; [Φοιτητής] y ζει στο μπαρ. >> [Bowden] Ναι. Κάπου σε αυτή τη μικρή πλατεία της μνήμης είναι ένα τετράγωνο που έχει littler y σε αυτό. Όταν επιστρέψω & y, είμαι επιστροφή ενός δείκτη σε αυτό το μικρό μπλοκ της μνήμης. Στη συνέχεια, όμως, όταν επιστρέφει μια συνάρτηση, το πλαίσιο της στοίβας παίρνει έσκασε από τη στοίβα. Και αυτός είναι ο λόγος που ονομάζεται στοίβα. Είναι σαν τη δομή δεδομένων στοίβας, αν γνωρίζετε τι είναι αυτό. Ή ακόμα και σαν μια στοίβα των δίσκων είναι πάντα το παράδειγμα, κύριες πρόκειται να πάει στον πάτο, τότε η πρώτη λειτουργία που θα καλέσετε για να πάει στην κορυφή του ότι, και δεν μπορείτε να πάρετε πίσω στην κύρια μέχρι να επιστρέψει από όλες τις λειτουργίες που έχουν κληθεί που έχουν τοποθετηθεί πάνω του. [Φοιτητής] Έτσι, αν το κάνετε επιστρέψετε το & y, ότι η τιμή μπορεί να αλλάξουν χωρίς προειδοποίηση. Ναι, it's - >> [φοιτητής] Θα μπορούσε να αντικατασταθεί. Ναι >>. Είναι εντελώς - Αν προσπαθήσετε και - Αυτό θα ήταν επίσης ένα μπαρ int * γιατί είναι επιστρέφοντας ένα δείκτη, έτσι τον τύπο της επιστροφής είναι int *. Εάν προσπαθήσετε να χρησιμοποιήσετε την τιμή επιστροφής της συνάρτησης, είναι απροσδιόριστη συμπεριφορά επειδή ότι ο δείκτης δείχνει σε κακή μνήμη. >> [Φοιτητής] Εντάξει. Τι κι αν, για παράδειγμα, έχετε δηλώσει int * y = malloc (sizeof (int)); Αυτό είναι καλύτερο. Ναι. [Φοιτητής] Μιλήσαμε για το πώς όταν σύρετε τα πράγματα σε κάδο ανακύκλωσης μας δεν είστε πραγματικά διαγράφονται? χάνουμε μόνο τους δείκτες. Έτσι, σε αυτή την περίπτωση δεν θα διαγράψει πραγματικά την αξία ή είναι ακόμα εκεί στη μνήμη; Για το μεγαλύτερο μέρος, αυτό πρόκειται να είναι ακόμα εκεί. Αλλά ας πούμε ότι τυχαίνει να καλέσει κάποια άλλη λειτουργία, baz. Baz πρόκειται να πάρει το δικό του πλαίσιο στοίβας του εδώ. Είναι πρόκειται να αντικαταστήσετε όλα αυτά τα πράγματα, και στη συνέχεια, αν αργότερα δοκιμάσετε και να χρησιμοποιήσετε το δείκτη που πήρατε πριν, δεν πρόκειται να είναι η ίδια αξία. Είναι πρόκειται να έχουν αλλάξει μόνο και μόνο επειδή σας ονομάζεται baz λειτουργία. [Μαθητής] Αλλά δεν είχαμε, θα έχουμε ακόμα 3; [Bowden] Κατά πάσα πιθανότητα, θα κάνατε. Αλλά δεν μπορείτε να βασιστείτε σε αυτό. Γ λέει μόνο απροσδιόριστη συμπεριφορά. [Φοιτητής] Ω, ναι. Εντάξει. Έτσι, όταν θέλετε να επιστρέψετε ένα δείκτη, αυτό είναι όπου malloc έρχεται σε χρήση. Γράφω πραγματικά επιστρέψει μόλις malloc (3 * sizeof (int)). Θα πάμε πάνω από malloc περισσότερο σε ένα δεύτερο, αλλά η ιδέα της malloc είναι το σύνολο των τοπικών μεταβλητών σας πάντα να πάτε στη στοίβα. Οτιδήποτε είναι malloced πηγαίνει στο σωρό, και θα είναι για πάντα και πάντα να είναι στο σωρό μέχρι να ελευθερώσετε ρητά. Έτσι, αυτό σημαίνει ότι όταν malloc κάτι, πρόκειται να επιβιώσει μετά την επιστροφή της λειτουργίας. [Φοιτητής] Θα επιβιώσει μετά το πρόγραμμα σταματάει; Όχι >> Εντάξει, γι 'αυτό πρόκειται να είναι εκεί μέχρι το πρόγραμμα είναι όλος ο τρόπος λειτουργίας γίνεται. Ναι >>. Μπορούμε να πάμε για τις λεπτομέρειες του τι συμβαίνει όταν το πρόγραμμα σταματάει. Ίσως χρειαστεί να μου θυμίζουν, αλλά ότι είναι ένα ξεχωριστό πράγμα εντελώς. [Φοιτητής] Έτσι malloc δημιουργεί ένα δείκτη; Ναι >>. Malloc - >> [φοιτητής] Νομίζω malloc ορίζει ένα μπλοκ μνήμης που ένας δείκτης μπορεί να χρησιμοποιήσει. [Bowden] θέλω αυτό το διάγραμμα πάλι. >> [Φοιτητής] Έτσι, η λειτουργία αυτή δουλεύει, όμως; [Φοιτητής] Ναι, malloc ορίζει ένα μπλοκ μνήμης που μπορείτε να χρησιμοποιήσετε, και τότε επιστρέφει την διεύθυνση του πρώτου μπλοκ του εν λόγω μνήμης. [Bowden] Ναι. Έτσι, όταν malloc, είστε αρπάζοντας κάποια μπλοκ της μνήμης αυτό είναι σήμερα στο σωρό. Εάν ο σωρός είναι πολύ μικρή, τότε ο σωρός είναι ακριβώς πρόκειται να αναπτυχθούν, και αναπτύσσεται προς την κατεύθυνση αυτή. Ας πούμε ότι ο σωρός είναι πολύ μικρή. Στη συνέχεια, αυτό είναι για να αυξηθεί λίγο και να επιστρέψει ένα δείκτη σε αυτό το μπλοκ που μόλις μεγάλωσε. Όταν δωρεάν πράγματα, θέλετε να κάνετε περισσότερο χώρο στο σωρό, έτσι τότε καλέστε αργότερα να μπορούν να επαναχρησιμοποιηθούν malloc ότι η μνήμη που είχατε προηγουμένως απελευθέρωσε. Το σημαντικό πράγμα για malloc και δωρεάν είναι ότι σας δίνει τον πλήρη έλεγχο κατά τη διάρκεια αυτών των μπλοκ μνήμης. Οι καθολικές μεταβλητές είναι πάντα ζωντανός. Οι τοπικές μεταβλητές είναι ζωντανοί στο πεδίο εφαρμογής τους. Μόλις περάσετε ένα στήριγμα σγουρά, οι τοπικές μεταβλητές είναι νεκροί. Malloced μνήμη είναι ζωντανή, όταν θέλετε να είναι ζωντανός και στη συνέχεια απελευθερώνεται όταν το πείτε να κυκλοφορήσει. Αυτά είναι πραγματικά τα μόνα 3 τύπους μνήμης, πραγματικά. Υπάρχει αυτόματη διαχείριση μνήμης, η οποία είναι η στοίβα. Πράγματα συμβαίνουν για σας αυτόματα. Όταν λέτε int x, μνήμη για int x. Όταν x βγαίνει από το πεδίο εφαρμογής, τη μνήμη ανακτάται για x. Στη συνέχεια, υπάρχει δυναμική διαχείριση μνήμης, η οποία είναι ό, τι είναι malloc, η οποία είναι όταν έχετε τον έλεγχο. Μπορείτε δυναμικά μνήμη αποφασίσει πότε πρέπει και δεν θα πρέπει να διατεθούν. Και έπειτα υπάρχει στατική, πράγμα που σημαίνει απλώς ότι ζει για πάντα, η οποία είναι ό, τι είναι καθολικές μεταβλητές. Είναι απλά πάντα στη μνήμη. Ερωτήσεις; [Φοιτητής] Μπορείτε να ορίσετε ένα μπλοκ μόνο με τη χρήση άγκιστρα αλλά δεν χρειάζεται να έχει μια δήλωση ή αν μια δήλωση, ενώ ή κάτι τέτοιο; Μπορείτε να ορίσετε ένα μπλοκ, όπως σε μια λειτουργία, αλλά ότι έχει άγκιστρα πάρα πολύ. [Φοιτητής] Έτσι, μπορείτε όχι μόνο να έχει σαν ένα τυχαίο ζευγάρι αγκύλες στον κώδικά σας που έχουν τοπικές μεταβλητές; >> Ναι, μπορείτε. Μέσα από int bar θα μπορούσαμε να έχουμε {int y = 3?}. Έτσι θεωρείται ότι είναι ακριβώς εδώ. Αλλά αυτό καθορίζει πλήρως το πεδίο της int y. Μετά από αυτό το δεύτερο στήριγμα σγουρά, y δεν μπορεί να χρησιμοποιηθεί πλέον. Μπορείτε σχεδόν ποτέ δεν το κάνουμε αυτό, όμως. Να πάρει πίσω ό, τι συμβαίνει όταν ένα πρόγραμμα τελειώνει, υπάρχει το είδος της ένα ψέμα παρανόηση / half που δίνουμε για να κάνει τα πράγματα λίγο πιο εύκολη. Θα σας πω ότι όταν διαθέτουν μνήμη είστε κατανομή κάποιο κομμάτι της μνήμης RAM για τη συγκεκριμένη μεταβλητή. Αλλά δεν είστε πραγματικά αγγίζει άμεσα RAM ποτέ μέσα στα προγράμματά σας. Αν νομίζετε ότι από αυτό, πώς επέστησε - Και στην πραγματικότητα, αν περάσει στο GDB θα δείτε το ίδιο πράγμα. Ανεξάρτητα από το πόσες φορές θα τρέξει το πρόγραμμά σας ή τι πρόγραμμα τρέχετε, η στοίβα είναι πάντα πρόκειται να ξεκινήσει - είστε πάντα πρόκειται να δούμε τις μεταβλητές γύρω από κάτι oxbffff διεύθυνση. Είναι συνήθως κάπου στην περιοχή αυτή. Αλλά πώς μπορεί 2 προγράμματα έχουν ενδεχομένως δείκτες για την ίδια μνήμη; [Φοιτητής] Υπάρχει κάποια αυθαίρετη ονομασία oxbfff όπου υποτίθεται ότι είναι για τη μνήμη RAM που μπορεί πραγματικά να είναι σε διαφορετικές θέσεις ανάλογα με το πότε η συνάρτηση κλήθηκε. Ναι. Ο όρος είναι εικονική μνήμη. Η ιδέα είναι ότι κάθε διαδικασία, κάθε πρόγραμμα που εκτελείται στον υπολογιστή σας έχει τη δική του - ας υποθέσουμε 32 bit - εντελώς ανεξάρτητο χώρο διευθύνσεων. Αυτό είναι ο χώρος διευθύνσεων. Έχει τη δική του εντελώς ανεξάρτητη 4 gigabytes του να χρησιμοποιήσει. Έτσι, αν έχετε τρέξει 2 προγράμματα ταυτόχρονα, το πρόγραμμα αυτό βλέπει 4 gigabyte στον εαυτό του, αυτό το πρόγραμμα βλέπει 4 gigabyte στον εαυτό του, και είναι αδύνατο για αυτό το πρόγραμμα για να dereference ένας δείκτης και να καταλήξουμε με τη μνήμη από αυτό το πρόγραμμα. Και ποια είναι η εικονική μνήμη είναι μια χαρτογράφηση από ένα χώρο διευθύνσεων διαδικασίες με τις πραγματικές πράγματα για RAM. Έτσι είναι μέχρι και το λειτουργικό σας σύστημα για να γνωρίζουμε ότι, hey, όταν αυτός ο τύπος oxbfff δείκτη dereferences, που πραγματικά σημαίνει ότι θέλει RAM byte 1000, ενώ αν αυτό το πρόγραμμα dereferences oxbfff, θέλει πραγματικά RAM byte 10000. Μπορούν να είναι αυθαίρετα μακριά. Αυτό ισχύει ακόμη και από τα πράγματα μέσα σε ένα ενιαίο χώρο διευθύνσεων διαδικασίες. Έτσι όπως βλέπει και τα 4 gigabytes στον εαυτό του, αλλά ας πούμε - [Φοιτητής] Μήπως κάθε ενιαία διαδικασία - Ας πούμε ότι έχετε ένα υπολογιστή με μόνο 4 gigabytes μνήμης RAM. Μήπως κάθε διαδικασία δείτε το σύνολο των 4 gigabyte; Ναι >>. Αλλά τα 4 gigabytes που βλέπει είναι ένα ψέμα. Είναι ακριβώς νομίζει ότι έχει όλα αυτή τη μνήμη, επειδή δεν γνωρίζει οποιαδήποτε άλλη διαδικασία υπάρχει. Θα χρησιμοποιήσει μόνο όσο μνήμης που χρειάζεται πραγματικά. Το λειτουργικό σύστημα δεν πρόκειται να δώσει RAM σε αυτή τη διαδικασία αν είναι δεν χρησιμοποιούν καμία μνήμη σε όλη αυτή την περιοχή. Δεν πρόκειται να δώσει τη μνήμη για αυτή την περιοχή. Αλλά η ιδέα είναι ότι - προσπαθώ να σκεφτώ - δεν μπορώ να σκεφτώ μια αναλογία. Οι αναλογίες είναι δύσκολο. Ένα από τα θέματα της εικονικής μνήμης ή ένα από τα πράγματα που είναι επίλυση είναι ότι οι διαδικασίες θα πρέπει να είναι εντελώς απληροφόρητοι ένα από το άλλο. Και έτσι μπορείτε να γράψετε οποιοδήποτε πρόγραμμα που μόλις dereferences κάθε δείκτη, ακριβώς όπως γράψετε ένα πρόγραμμα που λέει * (ox1234), εύρεση τιμών διεύθυνση μνήμης και ότι το 1234. Αλλά είναι στο χέρι του λειτουργικού συστήματος για να μεταφράσει τότε τι σημαίνει 1234. Έτσι, αν συμβεί 1234 να είναι μια έγκυρη διεύθυνση μνήμης για τη διαδικασία αυτή, σαν να είναι στη στοίβα ή κάτι, τότε αυτό θα επιστρέψει την αξία του εν λόγω διεύθυνση μνήμης όσον αφορά τη διαδικασία γνωρίζει. Αλλά αν δεν είναι 1234 μια έγκυρη διεύθυνση, όπως συμβαίνει να προσγειωθεί σε κάποιο μικρό κομμάτι της μνήμης που είναι εδώ πέρα ​​από το σωρό και πέρα ​​από το σωρό και δεν έχετε πραγματικά ότι χρησιμοποιείται, στη συνέχεια, ότι όταν μπορείτε να πάρετε τα πράγματα όπως segfaults επειδή είστε αγγίζει μνήμη που δεν πρέπει να αγγίξει. Αυτό είναι επίσης αλήθεια - Ένα σύστημα 32-bit, 32 bit σημαίνει ότι έχετε 32 bit για να ορίσετε μια διεύθυνση μνήμης. Είναι γιατί δείκτες είναι 8 bytes, επειδή 32 bits είναι 8 bytes - ή 4 bytes. Οι δείκτες είναι 4 bytes. Έτσι, όταν βλέπετε ένα δείκτη, όπως oxbfffff, δηλαδή - Μέσα σε κάθε συγκεκριμένο πρόγραμμα μπορείτε να δημιουργήσετε ένα οποιοδήποτε αυθαίρετο δείκτη, οπουδήποτε από ox0 να βόδι 8 f's - ffffffff. [Φοιτητής] Μήπως δεν σας λένε ότι είναι 4 bytes; Ναι >>. [Φοιτητής] Στη συνέχεια, κάθε byte θα έχει - >> [Bowden] Δεκαεξαδικό. Δεκαεξαδικό - 5, 6, 7, 8. Έτσι δείκτες θα πάμε να δούμε πάντα σε δεκαεξαδικό. Είναι ακριβώς το πώς θα κατατάξει δείκτες. Κάθε 2 ψηφία του δεκαεξαδικού είναι 1 byte. Έτσι, υπάρχει μετάβαση να είναι 8 δεκαεξαδικά ψηφία για 4 bytes. Έτσι, κάθε δείκτη σε ένα σύστημα 32-bit θα είναι 4 bytes, πράγμα που σημαίνει ότι στη διαδικασία σας μπορείτε να δημιουργήσετε οποιαδήποτε αυθαίρετη 4 bytes και να κάνει ένα δείκτη έξω από αυτό, πράγμα που σημαίνει ότι όσο γνωρίζει, δεν μπορεί να αντιμετωπίσει μια ολόκληρη 2 στις 32 bytes μνήμης. Ακόμα κι αν δεν έχει πραγματικά πρόσβαση σε αυτό, ακόμη και αν ο υπολογιστής σας έχει μόνο 512 megabytes, νομίζει ότι έχει τόσο πολύ μνήμη. Και το λειτουργικό σύστημα είναι αρκετά έξυπνος ότι θα χορηγήσουν μόνο ό, τι πραγματικά χρειάζεται. Δεν πήγαινε, ω, μια νέα διαδικασία: 4 συναυλίες. Ναι. >> [Φοιτητής] Τι σημαίνει το βόδι; Γιατί να το γράψετε; Είναι ακριβώς το σύμβολο για δεκαεξαδική. Όταν δείτε ένα ξεκίνημα με αριθμό βόδι, οι διαδοχικές πράγματα είναι δεκαεξαδικό. [Φοιτητής] Ήσουν εξηγώντας για το τι συμβαίνει όταν ένα πρόγραμμα τελειώνει. Ναι >>. Τι συμβαίνει όταν ένα πρόγραμμα τελειώνει είναι το λειτουργικό σύστημα απλά διαγράφει τις αντιστοιχίσεις που έχει για αυτές τις διευθύνσεις, και αυτό είναι όλο. Το λειτουργικό σύστημα μπορεί να δώσει τώρα μόλις ότι η μνήμη σε ένα άλλο πρόγραμμα να χρησιμοποιήσει. [Φοιτητής] Εντάξει. Έτσι, όταν διαθέτουν κάτι για το σωρό ή στοίβα ή τις καθολικές μεταβλητές ή οτιδήποτε, όλοι απλά εξαφανίζονται μόλις τελειώσει το πρόγραμμα επειδή το λειτουργικό σύστημα είναι πλέον ελεύθερος να δοθούν σε αυτή την μνήμη σε οποιαδήποτε άλλη διαδικασία. [Φοιτητής] Ακόμα κι αν υπάρχουν πιθανώς ακόμα τιμές αναγράφονται σε; Ναι >>. Οι τιμές είναι πιθανό ακόμα εκεί. Είναι ακριβώς πρόκειται να είναι δύσκολο να πάρει σε αυτά. Είναι πολύ πιο δύσκολο να πάρει τους σε ό, τι είναι να πάρει σε ένα διαγραμμένο αρχείο επειδή η διαγραφή αρχείων από το είδος βρίσκεται εκεί για μεγάλο χρονικό διάστημα και ο σκληρός δίσκος είναι πολύ μεγαλύτερο. Έτσι πρόκειται να αντικαταστήσει διάφορα μέρη της μνήμης πριν αυτό συμβεί να αντικαταστήσετε το κομμάτι της μνήμης ότι ο φάκελος που χρησιμοποιείται για να είναι. Αλλά κύρια μνήμη, μνήμη RAM, θα τον κύκλο μέσα από μια πολύ πιο γρήγορα, έτσι πρόκειται να είναι πολύ γρήγορα να αντικατασταθούν. Ερωτήσεις για το θέμα αυτό ή κάτι άλλο; [Φοιτητής] Έχω ερωτήσεις σχετικά με ένα διαφορετικό θέμα. Εντάξει >>. Υπάρχει κάποιος που έχει ερωτήσεις σχετικά με αυτό; Εντάξει. Διαφορετικές θέμα. >> [Φοιτητής] Εντάξει. Πήγαινα σε μερικές από τις δοκιμές πρακτική, και σε ένα από αυτά ήταν μιλάμε για το sizeof και η τιμή που επιστρέφει ή διαφορετικούς τύπους μεταβλητών. Ναι >>. Και είπε ότι και οι δύο int και καιρό τόσο την επιστροφή 4, έτσι είναι και οι δύο μήκος 4 byte. Υπάρχει κάποια διαφορά μεταξύ int και ένα καιρό εκεί, ή είναι το ίδιο πράγμα; Ναι, υπάρχει μια διαφορά. Το πρότυπο C - Είμαι κατά πάσα πιθανότητα θα χαλάσουν. Το πρότυπο C είναι ακριβώς όπως αυτό είναι C, η επίσημη τεκμηρίωση του C. Αυτό είναι ό, τι λέει. Έτσι, η C πρότυπο λέει απλά ότι ένας char θα είναι για πάντα και πάντα να είναι 1 byte. Τα πάντα μετά από αυτό - μια σύντομη είναι πάντα ακριβώς ορίζεται ως μεγαλύτερη από ή ίση με ένα char. Αυτό μπορεί να είναι αυστηρά μεγαλύτερο από, αλλά όχι θετική. Μια int είναι ακριβώς ορίζεται ως μεγαλύτερη ή ίση με μια σύντομη. Και ένα μακρύ είναι ακριβώς ορίζεται ως μεγαλύτερη ή ίση με έναν int. Και ένα μακρύ χρονικό διάστημα είναι μεγαλύτερο από ή ίσο με ένα μακρύ. Έτσι, το μόνο πράγμα που η C είναι πρότυπο ορίζει η σχετική παραγγελία του τα πάντα. Το πραγματικό ποσό της μνήμης που καταλαμβάνουν τα πράγματα είναι γενικά μέχρι την υλοποίηση, αλλά είναι αρκετά καλά που ορίζονται σε αυτό το σημείο. >> [Φοιτητής] Εντάξει. Έτσι, σορτς είναι σχεδόν πάντα θα είναι 2 bytes. Ints είναι σχεδόν πάντα θα είναι 4 bytes. Long επιμήκη προϊόντα είναι σχεδόν πάντα θα είναι 8 bytes. Και longs, αυτό εξαρτάται από το αν είστε με τη χρήση 32-bit ή 64-bit σύστημα. Έτσι, ένα μακρύ πρόκειται να αντιστοιχεί με τον τύπο του συστήματος. Αν χρησιμοποιείτε ένα σύστημα 32-bit, όπως η συσκευή, πρόκειται να είναι 4 bytes. Εάν χρησιμοποιείτε μια έκδοση 64-bit σαν μια παρτίδα των πρόσφατων υπολογιστές, πρόκειται να είναι 8 bytes. Ints είναι σχεδόν πάντα 4 byte σε αυτό το σημείο. Long επιμήκη προϊόντα είναι σχεδόν πάντα 8 bytes. Στο παρελθόν, ints χρησιμοποιείται για να είναι μόνο 2 bytes. Αλλά παρατηρήσετε ότι αυτό ικανοποιεί πλήρως όλες αυτές τις σχέσεις και μεγαλύτερη από ό, τι ίσο με. Ενόσω είναι τέλεια επιτρέπεται να είναι το ίδιο μέγεθος με έναν ακέραιο αριθμό, και είναι επίσης επιτρέπεται να είναι το ίδιο μέγεθος με ένα μακρύ διάστημα. Και είναι ακριβώς έτσι συμβαίνει να είναι ότι το 99,999% των συστημάτων, που θα είναι ίσο με το είτε int ή πολύ μεγάλο χρονικό διάστημα. Εξαρτάται μόνο σε 32-bit ή 64-bit. >> [Φοιτητής] Εντάξει. Σε άρματα, πώς είναι το δεκαδικό σημείο που ορίζεται από την άποψη των bits; Όπως και το δυαδικό; Ναι >>. Δεν χρειάζεται να γνωρίζουν ότι για CS50. Δεν μαθαίνουν ότι ακόμα και σε 61. Δεν μαθαίνουν ότι πραγματικά σε κάθε μάθημα. Είναι απλά μια αναπαράσταση. Ξεχάσω τις ακριβείς διανομές λίγο. Η ιδέα της κινητής υποδιαστολής είναι ότι διαθέτουν ένα συγκεκριμένο αριθμό των bits να εκπροσωπεί - Βασικά, όλα είναι σε επιστημονική σημειογραφία. Έτσι, θα διαθέσει ένα συγκεκριμένο αριθμό των bits να εκπροσωπεί τον αριθμό τους, όπως το 1,2345. Ποτέ δεν μπορεί να αντιπροσωπεύει έναν αριθμό με περισσότερα ψηφία από 5. Στη συνέχεια, μπορείτε επίσης να διαθέτουν ένα συγκεκριμένο αριθμό bits έτσι ώστε να τείνει να είναι σαν μπορείτε να πάτε μόνο μέχρι ένα ορισμένο αριθμό, όπως αυτός είναι ο μεγαλύτερος εκθέτης που μπορείτε να έχετε, και μπορείτε να πάτε μόνο μέχρι ένα ορισμένο εκθέτη, όπως αυτό είναι το μικρότερο εκθέτη μπορείτε να έχετε. Δεν θυμάμαι τα ακριβή τρόπο bits ανατεθεί σε όλες αυτές τις αξίες, αλλά ένα ορισμένο αριθμό από bits είναι αφιερωμένο στην 1,2345, άλλο συγκεκριμένο αριθμό bits είναι αφιερωμένο στον εκθέτη, και αυτό είναι μόνο δυνατό να αποτελούν εκθέτης ενός ορισμένου μεγέθους. [Φοιτητής] Και ένα διπλό; Είναι αυτό σαν ένα πολύ μακρύ float; Ναι >>. Είναι το ίδιο πράγμα με ένα άρμα, εκτός από τώρα είστε με τη χρήση 8 byte αντί των 4 byte. Τώρα θα είστε σε θέση να χρησιμοποιήσει 9 ψηφία ή 10 ψηφία, και αυτό θα είναι σε θέση να πάει μέχρι και 300 αντί για 100. >> [Φοιτητής] Εντάξει. Και είναι επίσης επιπλέει 4 bytes. Ναι >>. Λοιπόν, και πάλι, αυτό εξαρτάται από τη συνολική πιθανώς για γενική εφαρμογή, επιπλέει αλλά είναι 4 bytes, δίκλινα είναι 8. Διπλό καλούνται διπλό επειδή είναι διπλάσιο από το μέγεθος των αρμάτων. [Φοιτητής] Εντάξει. Και υπάρχουν διπλασιάζει διπλό; >> Δεν υπάρχουν. Νομίζω - >> [φοιτητής] Σας αρέσει το μεγάλο επιμήκη προϊόντα; Ναι >>. Δε νομίζω. Ναι. [Φοιτητής] Στις δοκιμή του περασμένου έτους υπήρξε μια ερώτηση σχετικά με την κύρια λειτουργία χρειάζεται να είναι μέρος του προγράμματός σας. Η απάντηση ήταν ότι δεν πρέπει να είναι μέρος του προγράμματός σας. Σε τι κατάσταση; Αυτό είναι ό, τι είδα. [Bowden] Φαίνεται - >> [φοιτητής] Τι κατάσταση; Έχετε το πρόβλημα; >> [Φοιτητής] Ναι, μπορώ να τραβήξει σίγουρα επάνω. Δεν πρέπει να είναι, από τεχνική άποψη, αλλά βασικά πρόκειται να είναι. [Φοιτητής] είδα ένα σε διαφορετικό έτος. Ήταν σαν Σωστό ή Λάθος: Ένα έγκυρο - >> Ω, ένα αρχείο c.; . [Φοιτητής] Κάθε αρχείο πρέπει να έχει γ - [και οι δύο μιλούν ταυτόχρονα - ακατάληπτο] Εντάξει. Έτσι, αυτό είναι ξεχωριστό. Ένα αρχείο. Γ πρέπει απλά να περιέχει λειτουργίες. Μπορείτε να μεταγλωττίσετε ένα αρχείο σε κώδικα μηχανής, δυαδική, οτιδήποτε, χωρίς να είναι εκτελέσιμο ακόμα. Ένα έγκυρο εκτελέσιμο αρχείο πρέπει να έχει μια κύρια λειτουργία. Μπορείτε να γράψετε το 100 λειτουργεί σε 1 αρχείο, αλλά δεν κύριο και στη συνέχεια να μεταγλωττίσετε ότι κάτω στο δυαδικό, τότε μπορείτε να γράψετε ένα άλλο αρχείο που έχει μόνο κύριο, αλλά απαιτεί ένα σωρό από αυτές τις λειτουργίες σε αυτό το δυαδικό αρχείο εδώ. Και έτσι, όταν κάνεις το εκτελέσιμο, αυτό είναι που κάνει ο σύνδεσμος είναι αυτό που συνδυάζει αυτά τα 2 δυαδικά αρχεία σε ένα εκτελέσιμο αρχείο. Έτσι, ένα αρχείο. Γ. δεν πρέπει να έχουν μια βασική λειτουργία σε όλα. Και σε μεγάλες βάσεις κώδικα θα δείτε χιλιάδες αρχεία. Γ και 1 κύριο αρχείο. Περισσότερες ερωτήσεις; [Φοιτητής] Υπήρχε ένα άλλο ζήτημα. Είπε να είναι ένα μεταγλωττιστή. Σωστό ή Λάθος; Και η απάντηση ήταν ψευδείς, και κατάλαβα γιατί δεν είναι σαν Clang. Αλλά τι να λέμε, αν δεν είναι; Κάνετε είναι βασικά ακριβώς - Μπορώ να δω ακριβώς τι ζητά. Αλλά λειτουργεί μόνο εντολές. Κάνετε. Μπορώ να τραβήξει αυτό επάνω. Ναι. Ω, ναι. Βεβαιωθείτε επίσης ότι κάνει. Αυτό λέει ο σκοπός της χρησιμότητας κάνουν είναι να προσδιορίσει αυτόματα ποια κομμάτια ενός μεγάλου προγράμματος θα πρέπει να αναθεωρείται και εκδίδει τις εντολές για να μεταγλωττίσετε τους. Μπορείτε να κάνετε τα αρχεία που είναι απολύτως τεράστια. Κάντε εξετάζει τις σφραγίδες του χρόνου και των αρχείων, όπως είπαμε πριν, μπορείτε να συντάξετε μεμονωμένα αρχεία κάτω, και δεν είναι μέχρι να φτάσετε στο συνδετήρα ότι από όπου και αν βάλει μαζί σε ένα εκτελέσιμο αρχείο. Έτσι, αν έχετε 10 διαφορετικά αρχεία και να κάνετε μια αλλαγή σε 1 από αυτά, τότε τι μάρκα πρόκειται να κάνει είναι απλά recompile ότι 1 αρχείο και επανασύνδεση τότε τα πάντα μαζί. Αλλά είναι πολύ dumber από αυτό. Είναι στο χέρι σας να καθορίσει πλήρως ότι αυτό είναι ό, τι θα έπρεπε να κάνει. Είναι εξ ορισμού έχει την ικανότητα να αναγνωρίζουν αυτά τα πράγματα σφραγίδα του χρόνου, αλλά μπορείτε να γράψετε ένα αρχείο μάρκα να κάνει τίποτα. Μπορείτε να γράψετε ένα αρχείο κάνουν έτσι ώστε όταν πληκτρολογείτε κάνει μόνο cd σε άλλο κατάλογο. Είχα πάρει απογοητευμένοι γιατί πάντα καρφί στο εσωτερικό της συσκευής μου και τότε θα δείτε το PDF από το Mac. Γι 'αυτό πηγαίνετε στο Finder και μπορώ να κάνω Go, Σύνδεση στο διακομιστή, και ο server θα συνδεθεί με συσκευή μου είναι, και στη συνέχεια θα ανοίξει το PDF που παίρνει συγκεντρώθηκαν από LaTeX. Αλλά είχα πάρει απογοητευμένοι γιατί κάθε φορά που χρειάζεται για να ανανεώσετε το PDF, Έπρεπε να το αντιγράψετε σε ένα συγκεκριμένο κατάλογο που θα μπορούσαν να έχουν πρόσβαση και είχε πάρει ενοχλητικό. Έτσι, αντί έγραψα ένα αρχείο μάρκα, τα οποία θα πρέπει να ορίσετε τον τρόπο αυτό καθιστά τα πράγματα. Πώς να κάνετε σε αυτό είναι PDF LaTeX. Ακριβώς όπως και κάθε άλλο αρχείο make - ή υποθέτω ότι δεν έχετε δει τα αρχεία μάρκα, αλλά έχουμε στη συσκευή ένα παγκόσμιο αρχείο μάρκα που απλά λέει, αν τη συγκρότηση του φακέλου C, χρησιμοποιήστε Clang. Και έτσι εδώ σε αρχείο μάρκα μου ότι κάνω λέω, αυτό το αρχείο που πρόκειται να θέλουν να συγκεντρώσει με PDF LaTeX. Και γι 'αυτό είναι PDF LaTeX που κάνει το compiling. Κάντε την κατάρτιση δεν είναι. Είναι τρέχει μόνο αυτές τις εντολές με τη σειρά που αναφέρονται. Γι 'αυτό τρέχει PDF LaTeX, το αντιγράφει στον κατάλογο θέλω να αντιγραφεί, το cd του στον κατάλογο και να κάνει άλλα πράγματα, αλλά το μόνο που κάνει είναι να αναγνωρίσουν πότε ένα αρχείο αλλάζει, και αν αλλάζει, τότε θα εκτελέσετε τις εντολές που είναι υποτίθεται για να τρέξει όταν οι αλλαγές στο αρχείο. >> [Φοιτητής] Εντάξει. Δεν ξέρω όπου τα παγκόσμια αρχεία μάρκα είναι για μένα για να το ελέγξουμε. Άλλες ερωτήσεις; Τίποτα από το παρελθόν κουίζ; Οποιαδήποτε πράγματα δείκτη; Υπάρχουν λεπτές πράγματα με δείκτες όπως - Είμαι δεν πρόκειται να είναι σε θέση να βρείτε ένα κουίζ ερώτηση σχετικά με αυτό - αλλά ακριβώς όπως αυτό το είδος του πράγματος. Βεβαιωθείτε ότι έχετε κατανοήσει ότι όταν λέω int * x * y - Αυτό δεν είναι ακριβώς κάτι εδώ, υποθέτω. Αλλά όπως * x * y, αυτά είναι 2 μεταβλητές που βρίσκονται στη στοίβα. Όταν λέω x = malloc (sizeof (int)), x εξακολουθεί να είναι μια μεταβλητή στη στοίβα, malloc είναι μερικά μπλοκ πάνω στο σωρό, και είμαστε με το σημείο x στο σωρό. Έτσι, κάτι σχετικά με τα σημεία στοίβα στο σωρό. Όποτε malloc τίποτα, είστε αποθήκευση αναπόφευκτα μέσα από ένα δείκτη. Έτσι ώστε το δείκτη βρίσκεται στη στοίβα, η malloced μπλοκ είναι στο σωρό. Πολλοί άνθρωποι μπερδεύονται και να πω int * x = malloc? X είναι στο σωρό. Όχι. Τι δείχνει x είναι στο σωρό. x είναι η ίδια στη στοίβα, εκτός αν για οποιοδήποτε λόγο έχετε x είναι μια καθολική μεταβλητή, στην οποία περίπτωση συμβαίνει να είναι σε μια άλλη περιοχή της μνήμης. Έτσι, την παρακολούθηση, αυτά τα διαγράμματα κουτί και το βέλος είναι αρκετά κοινό για το κουίζ. Ή αν δεν είναι σε κουίζ 0, θα είναι σε κουίζ 1. Θα πρέπει να γνωρίζετε όλα αυτά, τα βήματα στην κατάρτιση δεδομένου ότι θα έπρεπε να απαντήσει σε ερωτήσεις σχετικά με αυτούς. Ναι. [Φοιτητής] Θα μπορούσαμε να πάμε πάνω σε αυτές τις ενέργειες - Σίγουρα >>. Πριν από την κατάρτιση και τα βήματα που έχουμε προεπεξεργασία, την κατάρτιση, τη συναρμολόγηση, και τη σύνδεση. Προεπεξεργασία. Τι σημαίνει ότι κάνω; Είναι το πιο εύκολο βήμα - καλά, όχι όπως - αυτό δεν σημαίνει ότι θα πρέπει να είναι προφανές, αλλά είναι το πιο εύκολο βήμα. Εσείς θα μπορούσαν να εφαρμόσουν οι ίδιοι. Ναι. [Φοιτητής] Πάρτε ό, τι έχετε σε σας όπως αυτό περιλαμβάνει και το αντιγράφει και στη συνέχεια, επίσης, καθορίζει. Φαίνεται ότι για τα πράγματα όπως # include και # define, και απλά αντίγραφα και πάστες τι πραγματικά σημαίνουν αυτά. Έτσι, όταν λέτε # include cs50.h, ο Preprocessor είναι αντιγραφή και επικόλληση cs50.h σε αυτή τη γραμμή. Όταν λέτε # define x να είναι 4, ο προεπεξεργαστής περνά μέσα από το σύνολο του προγράμματος και αντικαθιστά όλες τις εμφανίσεις του x με 4. Έτσι, ο προεπεξεργαστής παίρνει ένα έγκυρο αρχείο C και εξάγει ένα έγκυρο αρχείο C όπου τα πράγματα έχουν αντιγραφεί και επικολληθεί. Έτσι τώρα κατάρτιση. Τι σημαίνει ότι κάνω; [Φοιτητής] Πηγαίνει από C σε δυαδικό. [Bowden] Δεν πάνε όλα το δρόμο σε δυαδικό. [Φοιτητής] Να κώδικα μηχανής τότε; >> Δεν είναι κώδικα μηχανής. [Φοιτητής] Συνέλευση; >> Συνέλευση. Πηγαίνει στην Συνέλευση προτού να πάει σε όλη τη διαδρομή στον κώδικα C, και περισσότερες γλώσσες κάνουν κάτι τέτοιο. Διαλέξτε οποιαδήποτε γλώσσα υψηλού επιπέδου, και αν πρόκειται να το υπολογίσουν, είναι πιθανό να συγκεντρώσει σε βήματα. Πρώτον, πρόκειται να μεταγλωττίσετε την Python στο C, τότε πρόκειται για την κατάρτιση C έως Συνέλευση, Συνέλευση και στη συνέχεια πρόκειται να πάρει μεταφραστεί σε δυαδική. Έτσι, την κατάρτιση πρόκειται να το φέρει από C έως Συνέλευση. Η λέξη σημαίνει συνήθως την κατάρτιση φέρνοντας το από ένα υψηλότερο επίπεδο σε χαμηλότερο γλώσσα προγραμματισμού υψηλού επιπέδου. Έτσι, αυτό είναι το μόνο βήμα για την συλλογή όπου μπορείτε να ξεκινήσετε με μια υψηλού επιπέδου γλώσσα και να καταλήξουμε σε μια χαμηλού επιπέδου γλώσσα, και γι 'αυτό το βήμα ονομάζεται κατάρτιση. [Φοιτητής] Κατά τη διάρκεια της κατάρτισης, ας πούμε ότι έχετε κάνει # include cs50.h. Θα το μεταγλωττιστή recompile το cs50.h, όπως και τις λειτουργίες που είναι εκεί, και τη μεταφράζουν σε κώδικα Συνέλευση, καθώς και, ή θα το αντιγράψετε και να επικολλήσετε κάτι που είναι ήδη προ-Συνέλευση; cs50.h θα λίγο πολύ ποτέ δεν καταλήγουν σε Συνέλευσης. Πράγματα όπως πρωτότυπα λειτουργία και τα πράγματα είναι απλά για σας να είστε προσεκτικοί. Εγγυάται ότι ο compiler μπορεί να ελέγξει τα πράγματα όπως είστε καλώντας λειτουργίες με τους τύπους δικαίωμα επιστροφής και τα σωστά επιχειρήματα και πράγματα. Έτσι cs50.h θα προεπεξεργασία στο αρχείο, και στη συνέχεια, όταν αυτό είναι σύνταξη Είναι βασικά πετιούνται μετά κάνει σίγουρος ότι όλα καλείται σωστά. Αλλά οι συναρτήσεις που ορίζονται στη βιβλιοθήκη CS50, που είναι ξεχωριστό από cs50.h, αυτά δεν θα καταρτίζονται χωριστά. Αυτό στην πραγματικότητα θα κατέβει στο στάδιο διασύνδεσης, έτσι θα φτάσουμε σε αυτό σε ένα δευτερόλεπτο. Αλλά πρώτα, τι είναι συναρμολόγηση; [Φοιτητής] Συνέλευση σε δυαδικό; Ναι >>. Συναρμολόγηση. Εμείς δεν αποκαλούμε την κατάρτιση Συνέλευση επειδή είναι λίγο πολύ μια καθαρή μετάφραση του δυαδικού. Υπάρχει πολύ λίγη λογική για να μεταβούν από συνέλευση σε δυαδικό. Είναι ακριβώς όπως την αναζήτηση σε έναν πίνακα, oh, έχουμε αυτή την εντολή? που αντιστοιχεί σε δυαδικό 01110. Και έτσι τα αρχεία που συναρμολόγηση γενικά έξοδοι. O αρχεία. Και τα αρχεία. O είναι αυτό που λέγαμε πριν, πώς ένα αρχείο δεν χρειάζεται να έχει μια κύρια λειτουργία. Κάθε αρχείο μπορεί να συγκεντρωθεί σε ένα αρχείο. O εφ 'όσον αυτό είναι ένα έγκυρο αρχείο C. Μπορεί να συγκεντρωθεί σε. O. Τώρα, η σύνδεση είναι αυτό που φέρνει πραγματικά ένα μάτσο. O αρχεία και τους φέρνει σε ένα εκτελέσιμο αρχείο. Και έτσι τι κάνει διασύνδεση είναι ότι μπορείτε να σκεφτείτε το CS50 βιβλιοθήκη ως ένα αρχείο. O. Πρόκειται για ένα ήδη καταρτίζονται δυαδικό αρχείο. Και έτσι κατά τη μεταγλώττιση του αρχείου σας, hello.c σας, η οποία καλεί GetString, hello.c παίρνει συγκεντρώνονται σε hello.o, hello.o είναι τώρα σε δυαδικό. Χρησιμοποιεί GetString, γι 'αυτό πρέπει να πάει πάνω σε cs50.o, και ο σύνδεσμος τους smooshes μαζί και αντιγράφει GetString σε αυτό το αρχείο και βγαίνει με ένα εκτελέσιμο αρχείο που έχει όλες τις λειτουργίες που χρειάζεται. Έτσι cs50.o δεν είναι στην πραγματικότητα ένα O αρχείο, αλλά είναι αρκετά κοντά ότι δεν υπάρχει θεμελιώδης διαφορά. Έτσι, συνδέοντας απλά φέρνει μια δέσμη των αρχείων μαζί που περιέχουν χωριστά όλες τις λειτουργίες που πρέπει να χρησιμοποιήσετε και δημιουργεί το εκτελέσιμο αρχείο που θα λειτουργεί πραγματικά. Και έτσι αυτό είναι επίσης αυτό που λέγαμε πριν όπου μπορείτε να έχετε 1000. γ. αρχεία, που συγκεντρώνει όλα αυτά να. o αρχεία, η οποία θα λάβει κατά πάσα πιθανότητα λίγο, στη συνέχεια, αλλάζετε 1. γ. αρχείο. Το μόνο που χρειάζεται να μεταγλωττίσετε ότι 1. Αρχείο c και στη συνέχεια όλα τα άλλα επανασύνδεση, συνδέσει τα πάντα πίσω μαζί. [Φοιτητής] Όταν είμαστε σύνδεση γράφουμε lcs50; Ναι, έτσι-lcs50. Που σηματοδοτεί τη σημαία με τον συνδετήρα που θα πρέπει να συνδέει σε αυτήν τη βιβλιοθήκη. Ερωτήσεις; Έχουμε περάσει πάνω από δυαδικό, εκτός από το ότι 5 δευτερόλεπτα στην πρώτη διάλεξη; Δε νομίζω. Θα πρέπει να γνωρίζετε όλα τα μεγάλα Os ότι έχουμε περάσει πάνω, και θα πρέπει να είναι σε θέση, αν σας δώσαμε μια λειτουργία, θα πρέπει να είναι σε θέση να πω ότι είναι μεγάλη O, περίπου. Ή επίσης, μεγάλη O είναι τραχύ. Έτσι, αν δείτε φωλιασμένα for για looping πάνω από τον ίδιο αριθμό των πραγμάτων, όπως int i, i > [φοιτητής] n τετράγωνο. >> Τείνει να είναι n τετράγωνο. Αν έχετε τριπλή ένθετο, τείνει να είναι n κύβους. Έτσι, αυτό το είδος των πράγμα που πρέπει να είναι σε θέση να επισημάνει αμέσως. Θα πρέπει να γνωρίζετε το είδος εισαγωγής και το είδος φούσκα και να συγχωνεύσει το είδος και όλα αυτά. Είναι πιο εύκολο να καταλάβουμε γιατί είναι αυτές n τετράγωνο και n log n και όλα αυτά γιατί νομίζω ότι υπήρχε ένα κουίζ για ένα έτος, όταν σας δώσαμε βασικά η εφαρμογή του bubble sort και είπε, "Ποιος είναι ο χρόνος εκτέλεσης αυτής της λειτουργίας;" Έτσι, αν το αναγνωρίσει ως είδος φούσκα, τότε μπορείτε να πείτε αμέσως n τετράγωνο. Αλλά αν εξετάσουμε μόνο αυτό, δεν χρειάζεται καν να συνειδητοποιήσουμε είδος αυτό είναι φούσκα? μπορείτε απλά να το πω αυτό το κάνει αυτό και αυτό. Αυτό είναι ν τετράγωνο. [Φοιτητής] Υπάρχουν παραδείγματα σκληρή μπορείτε να έρθετε επάνω με εκεί, σαν μια παρόμοια ιδέα για την εξεύρεση; Δεν νομίζω ότι θα σας δώσω κάποια παραδείγματα σκληρή. Το πράγμα bubble sort είναι περίπου τόσο σκληρά όσο θα πάμε, και ακόμη ότι, εφ 'όσον μπορείτε να καταλάβετε ότι είστε πάνω από την επανάληψη του πίνακα για κάθε στοιχείο του πίνακα, ο οποίος πρόκειται να είναι κάτι που ν τετράγωνο. Υπάρχουν γενικές ερωτήσεις, όπως το δικαίωμα που έχουμε εδώ - Αχ. Ακριβώς η άλλη ημέρα, Doug ισχυρίστηκε, «έχω εφεύρει έναν αλγόριθμο που να ταξινομήσετε μια σειρά "N των αριθμών σε O (log n) χρόνο!" Λοιπόν, πώς ξέρουμε ότι είναι αδύνατο; [Ακούγεται ανταπόκριση των φοιτητών] >> Ναι. Τουλάχιστον, θα πρέπει να αγγίζουν το ένα στοιχείο του πίνακα, έτσι είναι αδύνατο να ταξινομήσετε μια σειρά από - Αν όλα είναι σε τάξη αδιαχώριστα, τότε θα πάμε να αγγίξετε τα πάντα στον πίνακα, έτσι είναι αδύνατο να το κάνει σε λιγότερο από O από n. [Φοιτητής] Θα μας έδειξε το παράδειγμα του να είναι σε θέση να το κάνουμε σε n O της αν χρησιμοποιείτε μια πολύ μνήμη. Ναι >>. Και that's - ξεχάσω τι that's - Είναι είδος καταμέτρηση; Χμμ. Αυτό είναι ένας ακέραιος αλγόριθμος ταξινόμησης. Έψαχνα για το ειδικό όνομα για αυτό που δεν μπορούσε να θυμηθεί την περασμένη εβδομάδα. Ναι. Αυτά είναι τα είδη των ειδών που μπορεί να επιτύχει τα πράγματα σε μεγάλο Ο του n. Αλλά υπάρχουν περιορισμοί, όπως μπορείτε να χρησιμοποιήσετε μόνο ακέραιοι μέχρι ένα ορισμένο αριθμό. Πλέον, αν προσπαθείτε να ταξινομήσετε that's κάτι - Αν σας είναι σειρά 012, -12, 151, 4 εκατ. ευρώ, τότε μόνο στοιχείο που πρόκειται να καταστρέψει εντελώς το σύνολο της διαλογής. Ερωτήσεις; [Φοιτητής] Αν έχετε μια αναδρομική συνάρτηση και κάνει ακριβώς τις αναδρομικές κλήσεις μέσα σε μια δήλωση επιστροφής, αυτό είναι ουρά αναδρομικό και έτσι δεν θα χρησιμοποιούν περισσότερη μνήμη ότι κατά τη διάρκεια της εκτέλεσης ή θα ήταν τουλάχιστον συγκρίσιμη χρήση μνήμης ως μια επαναληπτική λύση; [Bowden] Ναι. Θα ήταν πιθανό να είναι κάπως πιο αργή, αλλά δεν είναι πραγματικά. Ουρά αναδρομική είναι πολύ καλή. Κοιτάζοντας ξανά σε στοίβα πλαίσια, ας πούμε ότι έχουν την κύρια και έχουμε int bar (int x) ή κάτι τέτοιο. Αυτό δεν είναι ένα τέλειο αναδρομική συνάρτηση, αλλά μπαρ επιστροφή (x - 1). Έτσι, προφανώς, αυτή είναι εσφαλμένη. Χρειάζεται περιπτώσεις βάση και την ουσία. Αλλά η ιδέα εδώ είναι ότι αυτή είναι η ουρά αναδρομικό πράγμα που σημαίνει όταν κεντρικό μπαρ κλήσεις πρόκειται να πάρει πλαίσιο της στοίβας. Σε αυτό το πλαίσιο στοίβας υπάρχει πρόκειται να είναι ένα μικρό κομμάτι της μνήμης που αντιστοιχεί στο όρισμα x του. Και ας πούμε ότι έτσι συμβαίνει κυρίως να καλέσετε μπαρ (100)? Έτσι x πρόκειται να αρχίσει από το 100. Εάν ο μεταγλωττιστής αναγνωρίζει ότι αυτό αποτελεί μια ουρά αναδρομική συνάρτηση, στη συνέχεια, όταν bar κάνει αναδρομική κλήση της να απαγορεύσει, αντί να κάνει ένα νέο πλαίσιο στοίβας, η οποία είναι όπου η στοίβα αρχίζει να αυξάνεται σε μεγάλο βαθμό, τελικά θα τρέξει στο σωρό και στη συνέχεια μπορείτε να πάρετε segfaults επειδή η μνήμη αρχίζει να συγκρούονται. Έτσι, αντί να κάνει το δικό του πλαίσιο στοίβας, μπορεί να συνειδητοποιήσουμε, hey, εγώ ποτέ δεν πρέπει να επανέλθουμε σε αυτό το πλαίσιο στοίβας, έτσι αντί εγώ θα αντικαταστήσει ακριβώς αυτό το επιχείρημα με το 99 και στη συνέχεια, ξεκινήστε μπαρ πάνω από όλα. Και τότε θα το κάνουμε και πάλι και θα φτάσουν μπαρ επιστροφής (x - 1), και αντί να κάνει ένα νέο πλαίσιο στοίβας, θα αντικαταστήσει μόνο σημερινό επιχείρημα του με 98 και στη συνέχεια άλμα πίσω στην αρχή του μπαρ. Οι πράξεις αυτές, αντικαθιστώντας, το 1 τιμή στη στοίβα και το άλμα πίσω στην αρχή, είναι αρκετά αποτελεσματική. Έτσι, δεν είναι μόνο αυτό το ίδιο χρήση μνήμης ως μια ξεχωριστή λειτουργία, η οποία είναι επαναληπτική επειδή είστε χρησιμοποιώντας μόνο 1 πλαίσιο στοίβα, αλλά δεν είστε που πάσχουν μειονεκτήματα της του χρειάζεται να καλέσετε λειτουργίες. Κλήση λειτουργίες μπορεί να είναι κάπως ακριβά, διότι έχει να κάνει όλες αυτές τις ρυθμίσεις και λύσιμο και όλα αυτά τα πράγματα. Έτσι, αυτή η αναδρομή ουράς είναι καλό. [Φοιτητής] Γιατί δεν δημιουργεί νέα μέτρα; Επειδή συνειδητοποιεί ότι δεν χρειάζεται να. Η κλήση στη γραμμή επιστρέφει μόλις την αναδρομική κλήση. Γι 'αυτό δεν χρειάζεται να κάνει τίποτα με την τιμή επιστροφής. Είναι ακριβώς πρόκειται να επιστρέψει αμέσως. Γι 'αυτό ακριβώς πρόκειται να αντικαταστήσουν το δικό του επιχείρημα και ξεκινήστε από την αρχή. Και επίσης, αν δεν έχετε την ουρά αναδρομική έκδοση, τότε μπορείτε να πάρετε όλα αυτά τα μπαρ, όπου όταν η γραμμή επιστρέφει πρέπει να επιστρέψει την αξία του σε αυτό, στη συνέχεια, ότι η γραμμή επιστρέφει αμέσως και επιστρέφει την αξία του σε αυτό το σημείο, τότε αυτό είναι ακριβώς πρόκειται να επιστρέψει αμέσως και να επιστρέψει την αξία του σε αυτό. Έτσι, είστε εξοικονόμηση αυτή βρεθώ όλα αυτά τα πράγματα από την στοίβα δεδομένου ότι η τιμή επιστροφής είναι ακριβώς πρόκειται να περάσει όλος ο τρόπος πίσω έτσι κι αλλιώς. Γιατί λοιπόν να μην αντικαταστήσει μόνο το επιχείρημά μας με το επικαιροποιημένο επιχείρημα και ξεκινήστε από την αρχή; Εάν η λειτουργία δεν είναι αναδρομική ουρά, αν κάνετε κάτι τέτοιο - [Φοιτητής] αν bar (x + 1). Ναι >>. Έτσι, αν το βάλετε σε κατάσταση, τότε κάνετε κάτι με την τιμή επιστροφής. Ή ακόμα και αν το κάνετε μόνο την επιστροφή 2 * bar (x - 1). Έτσι τώρα bar (x - 1) θα πρέπει να επιστρέψουν, προκειμένου να υπολογίσει 2 φορές ότι η αξία, έτσι τώρα χρειάζεται το δικό της ξεχωριστό πλαίσιο της στοίβας, και τώρα, δεν έχει σημασία πόσο σκληρά την προσπάθειά σας, εσείς πρόκειται να πρέπει να - Αυτό δεν είναι αναδρομική ουρά. [Φοιτητής] Θα προσπαθήσω να φέρω μια αναδρομή στο στόχο για μια αναδρομή ουρά - [Bowden] Σε έναν ιδανικό κόσμο, αλλά σε CS50 δεν έχετε να. Για να πάρετε αναδρομή ουρά, γενικά, θα δημιουργήσει ένα πρόσθετο επιχείρημα όπου θα λάβει μπαρ int x σε y και y αντιστοιχεί στον τελικό πράγμα που θέλετε να επιστρέψετε. Έτσι, τότε αυτό θα πάμε να επιστρέψει bar (x - 1), 2 * y. Έτσι, αυτό είναι απλώς μια υψηλού επιπέδου πώς θα μετατρέψει τα πράγματα να είναι αναδρομική ουρά. Αλλά το επιπλέον επιχείρημα - Και στη συνέχεια, στο τέλος, όταν φτάσετε βασικό σενάριο σας, μπορείτε να επιστρέψετε ακριβώς y επειδή έχετε συσσώρευση ολόκληρο το χρόνο η τιμή επιστροφής που θέλετε. Μπορείτε είδος του έχουν κάνει επαναληπτικά αλλά χρησιμοποιώντας αναδρομικές κλήσεις. Ερωτήσεις; [Φοιτητής] Ίσως για αριθμητική δείκτη, όπως όταν χρησιμοποιεί χορδές. Σίγουρα >>. Αριθμητική δείκτη. Όταν χρησιμοποιείτε χορδές είναι εύκολο, επειδή οι χορδές είναι char αστέρια, χαρακτήρες είναι για πάντα και πάντα ένα μόνο byte, και έτσι αριθμητική δείκτη είναι ισοδύναμη με κανονική αριθμητική όταν έχεις να κάνεις με χορδές. Ας πούμε char * s = "γεια". Έτσι έχουμε ένα μπλοκ στη μνήμη. Χρειάζεται 6 bytes, επειδή θα πρέπει να έχετε πάντα τη μηδενική τερματισμού. Και char * s πρόκειται να επισημάνω στην αρχή αυτού του πίνακα. Έτσι, s επισημαίνει εκεί. Τώρα, αυτό είναι βασικά το πώς λειτουργεί κάθε σειρά, ανεξάρτητα από το αν ήταν μια επιστροφή με malloc ή αν είναι στη στοίβα. Κάθε συστοιχία είναι βασικά ένας δείκτης προς την έναρξη της συστοιχίας, και στη συνέχεια, κάθε πράξη πίνακα, κάθε ευρετηρίασης, πρόκειται ακριβώς σε αυτή την σειρά ένα συγκεκριμένο offset. Έτσι, όταν λέω κάτι σαν s [3]? Αυτό πρόκειται να s και μετρώντας 3 χαρακτήρες μέσα Έτσι, s [3], έχουμε 0, 1, 2, 3, έτσι s [3] πρόκειται να αναφερθώ σε αυτό το l. [Φοιτητής] Και θα μπορούσαμε να φτάσει την ίδια αξία με τον τρόπο s + 3 και στη συνέχεια παρενθέσεις αστέρι; Ναι. Αυτό είναι ισοδύναμο με * (s + 3)? και ότι είναι για πάντα και πάντα ισοδύναμο δεν έχει σημασία τι θα κάνεις. Ποτέ δεν πρέπει να χρησιμοποιήσετε τη σύνταξη βραχίονα. Μπορείτε να χρησιμοποιείτε πάντα την * (s + 3) σύνταξη. Οι άνθρωποι έχουν την τάση να τους αρέσει η σύνταξη βραχίονα, όμως. [Φοιτητής] Έτσι, όλες οι σειρές είναι στην πραγματικότητα μόνο δείκτες. Υπάρχει μια μικρή διαφορά όταν λέω int x [4]? >> [Φοιτητής] Έχει δημιουργήσει αυτή τη μνήμη; [Bowden] Αυτό θα δημιουργήσει 4 ints στη στοίβα, έτσι συνολικά 16 bytes. Είναι πρόκειται να δημιουργήσει 16 byte στη στοίβα. x δεν αποθηκεύονται πουθενά. Είναι απλά ένα σύμβολο που αναφέρεται στην έναρξη του πράγματος. Επειδή έχετε δηλώσει τη σειρά μέσα από αυτή τη λειτουργία, τι ο compiler πρόκειται να κάνουμε είναι να αντικαταστήσει ακριβώς όλες τις εμφανίσεις της μεταβλητής x με όπου συνέβη να επιλέξουν να εφαρμόσουν αυτές τις 16 bytes. Δεν μπορεί να το κάνει αυτό με char * s, επειδή s είναι ένα πραγματικό δείκτη. Είναι ελεύθερος να επισημάνω στη συνέχεια σε άλλα πράγματα. χ είναι μια σταθερά. Δεν μπορείς να έχεις το σημείο σε μια διαφορετική σειρά. >> [Φοιτητής] Εντάξει. Αλλά αυτή η ιδέα, αυτή η ευρετηρίαση, είναι η ίδια, ανεξάρτητα από το αν πρόκειται για μια παραδοσιακή σειρά ή αν είναι ένας δείκτης για κάτι ή αν είναι ένας δείκτης σε μια σειρά malloced. Και στην πραγματικότητα, είναι τόσο ισοδύναμη ότι είναι επίσης το ίδιο πράγμα. Είναι πραγματικά ακριβώς μεταφράζεται αυτό που είναι μέσα από τα στηρίγματα και ό, τι έχει απομείνει από τα στηρίγματα, προσθέτει τους μαζί, και dereferences. Έτσι, αυτό είναι ακριβώς το ίδιο έγκυρη όπως * (s + 3) ή s [3]. [Φοιτητής] Μπορεί να έχετε δείκτες που δείχνουν σε 2-διαστάσεων πίνακες; Είναι πιο δύσκολο. Παραδοσιακά, ηο. Μια 2-διαστάσεων πίνακας είναι απλά ένα 1-διάστατο πίνακα με κάποιο βολικό σύνταξη γιατί όταν λέω int x [3] [3], αυτό είναι πραγματικά μόνο 1 πίνακα με 9 τιμές. Και έτσι όταν δείκτη, ο compiler ξέρει τι εννοώ. Αν πω x [1] [2], το ξέρει Θέλω να πάω στη δεύτερη σειρά, έτσι πρόκειται να παραλείψετε το πρώτο 3, και στη συνέχεια, θέλει το δεύτερο πράγμα που, γι 'αυτό πρόκειται να πάρει αυτό το ένα. Αλλά αυτό είναι ακόμα ένα απλό μονοδιάστατο πίνακα. Και έτσι, αν ήθελα να ορίσετε ένα δείκτη για την ποικιλία, Θα έλεγα int * p = x? Ο τύπος του x είναι ακριβώς - Είναι τραχύ τύπο λέγοντας του x δεδομένου ότι είναι απλώς ένα σύμβολο και δεν είναι μια πραγματική μεταβλητή, αλλά αυτό είναι μόνο ένα int *. χ είναι απλά ένας δείκτης για την έναρξη αυτής. >> [Φοιτητής] Εντάξει. Και γι 'αυτό δεν θα είναι σε θέση να έχουν πρόσβαση [1] [2]. Νομίζω ότι υπάρχει ειδική σύνταξη για την κήρυξη ενός δείκτη, κάτι γελοίο, όπως int (* p [-. κάτι εντελώς γελοίο που δεν γνωρίζουν καν. Αλλά υπάρχει ένα συντακτικό για τη δήλωση δείκτες, όπως με παρενθέσεις και δραστηριότητες. Δεν μπορεί ακόμη και να σας αφήσει να το κάνουμε αυτό. Θα μπορούσα να κοιτάξουμε πίσω σε κάτι που θα μπορούσε να μου πει την αλήθεια. Θα δούμε για αργότερα, αν υπάρχει ένα σημείο για σύνταξη. Αλλά ποτέ δεν θα το δείτε. Και ακόμα και η σύνταξη είναι τόσο αρχαϊκό ότι αν το χρησιμοποιείτε, οι άνθρωποι θα πρέπει να αμηχανία. Πολυδιάστατοι πίνακες είναι αρκετά σπάνιο, δεδομένου ότι είναι. Μπορείτε λίγο πολύ - Λοιπόν, αν κάνεις τα πράγματα μήτρα δεν πρόκειται να είναι σπάνια, αλλά σε C είστε σπάνια πρόκειται να χρησιμοποιείτε πολυδιάστατους πίνακες. Ναι. >> [Φοιτητής] Ας πούμε ότι έχετε ένα πραγματικά μεγάλο πίνακα. Έτσι, στην εικονική μνήμη φαίνεται να είναι όλα τα διαδοχικά, όπως και τα στοιχεία που το ένα δίπλα στο άλλο, αλλά στη φυσική μνήμη, θα ήταν δυνατό γι 'αυτό που πρόκειται να χωρίσουν; Ναι >>. Πώς λειτουργεί εικονική μνήμη είναι το χωρίζει μόνο - Η μονάδα της κατανομής είναι μια σελίδα, η οποία τείνει να είναι 4 kilobyte, και έτσι όταν μια διαδικασία λέει, hey, θέλω να χρησιμοποιήσω αυτή τη μνήμη, το λειτουργικό σύστημα πρόκειται να διαθέσει το 4 kilobyte για αυτό το μικρό μπλοκ μνήμης. Ακόμα και αν χρησιμοποιείτε μόνο μια μικρή byte σε ολόκληρο το μπλοκ της μνήμης, το λειτουργικό σύστημα πρόκειται να δώσει τα πλήρη 4 kilobyte. Έτσι τι αυτό σημαίνει είναι ότι θα μπορούσε να έχει - ας πούμε ότι αυτό είναι το stack μου. Αυτή η στοίβα μπορεί να διαχωριστεί. Stack μου θα μπορούσε να είναι megabytes και megabytes. Stack μου θα μπορούσε να είναι τεράστια. Αλλά η ίδια η στοίβα θα πρέπει να χωριστεί σε μεμονωμένες σελίδες, η οποία, αν κοιτάξουμε πάνω από εδώ ας πούμε αυτό είναι η μνήμη RAM μας, αν έχω 2 gigabytes μνήμης RAM, αυτό είναι πραγματική διεύθυνση 0, όπως η μηδενική byte της μνήμης RAM μου, και αυτό είναι 2 gigabytes σε όλη τη διαδρομή εδώ. Έτσι, αυτή η σελίδα θα μπορούσε να αντιστοιχεί σε αυτό το μπλοκ εδώ. Αυτή η σελίδα θα μπορούσε να αντιστοιχεί σε αυτό το μπλοκ εδώ. Αυτό και μόνο θα μπορούσε να αντιστοιχεί σε αυτό το σημείο εδώ. Έτσι, το λειτουργικό σύστημα είναι ελεύθερος να εκχωρήσει φυσική μνήμη σε κάθε σελίδα ξεχωριστά αυθαίρετα. Και αυτό σημαίνει ότι αν αυτό συμβαίνει στα σύνορα να μην συμπίπτει με μια σειρά, μια σειρά συμβαίνει να μείνει από αυτό και το δικαίωμα της παρούσας διάταξης μιας σελίδας, τότε η συστοιχία πρόκειται να χωριστεί σε φυσική μνήμη. Και στη συνέχεια, όταν κλείνετε το πρόγραμμα, όταν η διαδικασία τελειώνει, αυτές οι αντιστοιχίσεις να διαγραφούν και τότε είναι ελεύθερη να χρησιμοποιήσει αυτά τα μικρά τετράγωνα για άλλα πράγματα. Περισσότερες ερωτήσεις; [Φοιτητής] Η αριθμητική δείκτη. Ω ναι >>. Χορδές ήταν πιο εύκολο, αλλά κοιτάζοντας κάτι σαν ints, έτσι πίσω στο int x [4]? Είτε αυτό είναι ένας πίνακας ή αν είναι ένας δείκτης σε μια σειρά malloced από 4 ακέραιους αριθμούς, πρόκειται να αντιμετωπίζονται με τον ίδιο τρόπο. [Φοιτητής] Έτσι συστοιχίες είναι στο σωρό; [Bowden] Οι πίνακες δεν είναι στο σωρό. >> [Φοιτητής] Αχ. [Bowden] Αυτό το είδος της συστοιχίας τείνει να είναι στη στοίβα αν δεν δηλωθεί κατά - αγνοώντας καθολικές μεταβλητές. Μην χρησιμοποιείτε καθολικές μεταβλητές. Μέσα από μια συνάρτηση λέω int x [4]? Είναι πρόκειται να δημιουργήσει ένα 4-μπλοκ ακέραιο στη στοίβα για αυτή τη διάταξη. Αλλά αυτή η malloc (4 * sizeof (int))? Πρόκειται να πάει στο σωρό. Αλλά μετά από αυτό το σημείο μπορώ να χρησιμοποιήσω x και p σε λίγο πολύ τους ίδιους τρόπους, εκτός από τις εξαιρέσεις που είπα πριν για να μπορείτε να εκχωρήσετε εκ νέου σ.. Τεχνικά, τα μεγέθη τους είναι κάπως διαφορετικά, αλλά αυτό είναι τελείως άσχετο. Ποτέ δεν χρησιμοποιούν πραγματικά μεγέθη τους. Το p θα μπορούσα να πω σ. [3] = 2? Ή x [3] = 2? Μπορείτε να τα χρησιμοποιήσετε με τον ίδιο ακριβώς τρόπο. Έτσι αριθμητική δείκτη τώρα - Ναι. [Φοιτητής] Μην έχετε να κάνετε p * εάν έχετε τα στηρίγματα; Οι παρενθέσεις είναι μια σιωπηρή dereference. Εντάξει >>. Στην πραγματικότητα, επίσης, τι λέτε με το μπορείτε να πάρετε πολυδιάστατους πίνακες με δείκτες, τι μπορείτε να κάνετε είναι κάτι σαν, ας πούμε, int ** pp = malloc (sizeof (int *) * 5)? Εγώ απλώς θα γράψω όλα έξω πρώτα. Δεν ήθελα εκείνο το ένα. Εντάξει. Αυτό που έκανα είναι εδώ - Αυτό θα πρέπει να είναι σελ. [i]. Έτσι, pp είναι ένας δείκτης σε ένα δείκτη. Είσαι mallocing σελ. να επισημάνει μια σειρά από 5 αστέρια int. Έτσι, στη μνήμη έχετε στην σελ. στοίβα Είναι πρόκειται να επισημάνω για μια σειρά από 5 τετράγωνα τα οποία είναι όλα τους δείκτες. Και στη συνέχεια, όταν malloc εδώ κάτω, εγώ malloc ότι κάθε μία από αυτές τις μεμονωμένες δείκτες Πρέπει να επισημάνω ένα ξεχωριστό μπλοκ των 4 byte για το σωρό. Έτσι, αυτά τα σημεία σε 4 bytes. Και αυτό δείχνει ένα διαφορετικό 4 bytes. Και όλα αυτά στη δική τους 4 bytes. Αυτό μου δίνει ένα τρόπο για να γίνει πολυδιάστατη πράγματα. Θα μπορούσα να πω σελ. [3] [4], αλλά τώρα αυτό δεν είναι το ίδιο πράγμα με το πολυδιάστατο συστοιχίες επειδή πολυδιάστατων συστοιχίες που μεταφράζεται [3] [4] σε ένα ενιαίο αντιστάθμιση στη συστοιχία x. Αυτό σ. dereferences, πρόσβαση στο τρίτο δείκτη, τότε dereferences ότι και προσβάσεις - 4 θα είναι άκυρο - ο δεύτερος δείκτης. Ότι, όταν είχαμε το int x [3] [4], όπως πριν από ένα πολυδιάστατο πίνακα και όταν κάνετε διπλό βραχίονα είναι πραγματικά μόνο ένα dereference, είστε μετά από ένα μόνο δείκτη και στη συνέχεια ένα offset, αυτό είναι πραγματικά 2D αναφορές. Θα ακολουθήσουν 2 ξεχωριστά δείκτες. Έτσι, αυτό επίσης τεχνικά σας επιτρέπει να έχετε πολυδιάστατους πίνακες όπου κάθε επιμέρους array είναι διαφορετικά μεγέθη. Πιστεύω λοιπόν ότι ακανόνιστα πολυδιάστατους πίνακες είναι ό, τι λέγεται αφού πραγματικά το πρώτο πράγμα που θα μπορούσε να δείξει κάτι που έχει 10 στοιχεία, το δεύτερο πράγμα που θα μπορούσε να δείξει κάτι που έχει 100 στοιχεία. [Φοιτητής] Υπάρχει κάποιο όριο στον αριθμό των δεικτών μπορείτε να έχετε εκεί επισημαίνοντας άλλα δείκτες; Όχι >> Μπορείτε να έχετε int p *****. Επιστροφή στην αριθμητική δείκτη - >> [φοιτητής] Αχ. Ναι >>. [Φοιτητής] Αν έχω int *** p και στη συνέχεια να κάνω μια αποαναφοράς και λέω p * είναι ίση με την τιμή αυτή, είναι μόνο πρόκειται να κάνετε 1 επίπεδο εύρεση τιμών; Ναι >>. Έτσι, αν θέλετε να αποκτήσετε πρόσβαση το πράγμα ότι η τελευταία δείκτης δείχνει σε - Στη συνέχεια, κάνετε σ ***. Εντάξει >>. Έτσι, αυτό είναι τα σημεία p στο 1 μπλοκ, σημεία σε ένα άλλο μπλοκ, σημεία σε ένα άλλο μπλοκ. Στη συνέχεια, αν κάνετε * p = κάτι άλλο, τότε αλλάζουν αυτό τώρα το σημείο σε ένα άλλο μπλοκ. Εντάξει >>. [Bowden] Και αν αυτά malloced, τότε θα έχουν διαρρεύσει τώρα μνήμη εκτός και αν τυχαίνει να έχουν διαφορετικές αναφορές από αυτά δεδομένου ότι δεν μπορείτε να πάρετε πίσω σε εκείνες αυτά που μόλις πέταξε μακριά. Αριθμητική δείκτη. int x [4]? πρόκειται να διαθέσει μια σειρά από 4 ακέραιους αριθμούς όπου το χ πρόκειται να δείχνουν την αρχή της συστοιχίας. Έτσι, όταν λέω κάτι σαν x [1]? Θέλω να πάω να σημαίνει το δεύτερο ακέραιο στον πίνακα, το οποίο θα είναι αυτό. Αλλά πραγματικά, αυτό είναι 4 byte στη σειρά δεδομένου ότι αυτό ακέραιος καταλαμβάνει 4 bytes. Έτσι, μια μετατόπιση από 1 σημαίνει πραγματικά μια μετατόπιση από 1 φορές το μέγεθος του ό, τι ο τύπος της συστοιχίας είναι. Πρόκειται για μια σειρά από ακέραιους αριθμούς, έτσι ώστε να ξέρει να κάνει 1 φορές το μέγεθος του int όταν θέλει να αντισταθμίσει. Η άλλη σύνταξη. Θυμηθείτε ότι αυτό είναι ισοδύναμο με * (χ + 1)? Όταν λέω δείκτη + 1, τι οι αποδόσεις είναι η διεύθυνση ότι ο δείκτης αποθηκεύει συν 1 φορές το μέγεθος του τύπου του δείκτη. Έτσι, εάν x = ox100, τότε x + 1 = ox104. Και μπορείτε να καταχραστούν αυτό και να πω κάτι σαν char * c = (char *) x? και γ τώρα πρόκειται να είναι η ίδια διεύθυνση με το x. γ πρόκειται να είναι ίση προς ox100, αλλά γ + 1 πρόκειται να είναι ίση προς ox101 από αριθμητική δείκτη εξαρτάται από τον τύπο του δείκτη που προσθέτετε στο. Έτσι, γ + 1, φαίνεται στο γ, είναι ένας pointer σε char, έτσι πρόκειται να προσθέσετε 1 φορές το μέγεθος του char, η οποία είναι πάντα θα είναι 1, έτσι μπορείτε να πάρετε 101, ενώ αν το κάνω x, το οποίο είναι επίσης ακόμα 100, x + 1 θα είναι 104. [Φοιτητής] Μπορείτε να χρησιμοποιήσετε C + +, προκειμένου να προωθήσει το δείκτη του ποντικιού κατά 1; Ναι, μπορείτε. Δεν μπορείτε να το κάνετε αυτό, επειδή με x το x είναι απλώς ένα σύμβολο, είναι μια διαρκής? Δεν μπορείτε να αλλάξετε x. Αλλά γ συμβαίνει ακριβώς να είναι ένας δείκτης, έτσι c + + είναι απόλυτα έγκυρες και θα αυξηθεί κατά 1. Αν γ ήταν απλά μια int *, τότε το c + + θα είναι 104. + + Κάνει αριθμητική δείκτη ακριβώς όπως γ + 1 θα έχουν γίνει αριθμητική δείκτη. Αυτό είναι στην πραγματικότητα το πώς πολλά πράγματα όπως το είδος συγχώνευσης - Αντί για τη δημιουργία αντιγράφων των πραγμάτων, μπορείτε να περάσετε αντί - Όπως και αν ήθελα να περάσει αυτό το μισό του πίνακα - Ας σβήσει μερικά από αυτό. Ας πούμε ότι ήθελε να περάσει αυτή την πλευρά του πίνακα σε μια λειτουργία. Τι θα περάσει στη λειτουργία που εξασφαλίζει; Αν περάσει x, είμαι περνώντας αυτή τη διεύθυνση. Αλλά θέλω να περάσει αυτή τη συγκεκριμένη διεύθυνση. Λοιπόν, τι θα πρέπει να περάσει; [Φοιτητής] Pointer + 2; [Bowden] Έτσι, x + 2. Ναι. Αυτό πρόκειται να είναι η διεύθυνση. Θα πρέπει επίσης πολύ συχνά το βλέπουμε ως x [2] και στη συνέχεια, η διεύθυνση αυτού. Έτσι, θα πρέπει να πάρετε τη διεύθυνση του γιατί ο βραχίονας είναι μια έμμεση dereference. x [2] αναφέρεται στην αξία που είναι σε αυτό το πλαίσιο, και στη συνέχεια, θέλετε τη διεύθυνση του εν λόγω πλαισίου, έτσι λέτε & x [2]. Έτσι, αυτό είναι το πώς κάτι σε είδος συγχώνευσης που θέλετε να περάσει τη μισή λίστα για κάτι πραγματικά απλά να περάσει & x [2], και τώρα, όσον αφορά την αναδρομική κλήση εκφράζει την ανησυχία της, νέα σειρά μου αρχίζει εκεί. Τελευταία ερωτήσεις λεπτό. [Φοιτητής] Αν δεν τεθεί ένα εμπορικό ή - τι είναι αυτό που ονομάζεται; >> Star; [Φοιτητής] Star. >> Τεχνικά, χειριστής dereference, αλλά - >> [φοιτητής] Αποαναφορά. Αν δεν βάλετε ένα αστέρι ή ένα εμπορικό, τι θα συμβεί αν πω απλά y = x και x είναι ένας δείκτης; Ποιος είναι ο τύπος του y; >> [Φοιτητής] Θα πω μόνο ότι ο δείκτης του 2. Έτσι, αν απλώς να πω y = x, τώρα x και y το σημείο για το ίδιο πράγμα. >> [Φοιτητής] Σημείο για το ίδιο πράγμα. Και αν το x είναι ένα int pointer; >> Θα διαμαρτύρονται επειδή δεν μπορείτε να εκχωρήσετε δείκτες. [Φοιτητής] Εντάξει. Να θυμάστε ότι οι δείκτες, έστω και αν εμείς τους επιστήσει ως βέλη, πραγματικά όλα αυτά κατάστημα - int * x - x πραγματικά όλα είναι αποθήκευση είναι κάτι σαν ox100, που τυχαίνει να εκπροσωπεί ως δείχνοντας στο μπλοκ αποθηκεύονται σε 100. Έτσι, όταν λέω int * y = x? Είμαι απλά αντιγραφή ox100 σε y, που είμαστε ακριβώς πρόκειται να αντιπροσωπεύουν το y, επίσης δείχνει να ox100. Και αν πω int i = (int) x? Τότε εγώ πρόκειται να αποθηκεύσετε ό, τι η αξία του είναι ox100 μέσα από αυτό, αλλά τώρα πρόκειται να ερμηνευθεί ως ακέραιο αντί ενός δείκτη. Αλλά θα πρέπει να έχετε το cast ή αλλιώς θα διαμαρτύρονται. [Φοιτητής] Έτσι εννοείτε να ρίξει - Είναι πρόκειται να χύτευση του int x int ή χύτευση του y; [Bowden] Τι; [Φοιτητής] Εντάξει. Μετά από αυτές τις παρενθέσεις είναι εκεί πρόκειται να είναι μια χ ή ay εκεί; [Bowden] Είτε. x και y είναι ισοδύναμες. >> [Φοιτητής] Εντάξει. Επειδή είστε και οι δύο δείκτες. Ναι >>. [Φοιτητής] Έτσι θα αποθηκεύσει το δεκαεξαδικό 100 σε ακέραια μορφή; >> [Bowden] Ναι. Αλλά δεν είναι η αξία του ό, τι αυτό δείχνει. [Bowden] Ναι. >> [Φοιτητής] Έτσι απλά τη διεύθυνση στο ακέραιο μορφή. Εντάξει. [Bowden] Αν ήθελε να για κάποιο περίεργο λόγο, θα μπορούσε να ασχοληθεί αποκλειστικά με δείκτες και ποτέ ασχοληθεί με ακέραιους αριθμούς και απλά να είναι σαν int * x = 0. Στη συνέχεια θα πάμε για να πάρει πραγματικά μια φορά σύγχυση αριθμητική δείκτη ξεκινά συμβαίνει. Έτσι, οι αριθμοί που αποθηκεύετε είναι χωρίς νόημα. Είναι ακριβώς το πώς θα καταλήξετε την ερμηνεία τους. Έτσι, είμαι ελεύθερος να αντιγράψετε ox100 από έναν int * int σε μια, και είμαι ελεύθερος να αναθέσει - Μπορείτε πλέον κατά πάσα πιθανότητα πρόκειται να πάρει φώναξε σε casting για μη - Είμαι ελεύθερος να εκχωρήσετε κάτι σαν (int *) ox1234 σε αυτό το αυθαίρετο * int. Έτσι ox123 είναι εξίσου έγκυρη μια διεύθυνση μνήμης είναι όπως και y. & Y συμβαίνει να επιστρέψει κάτι που είναι λίγο πολύ ox123. [Φοιτητής] Θα ότι είναι ένα πραγματικά δροσερό τρόπο για να πάει από δεκαεξαδικό σε δεκαδική μορφή, όπως και αν έχετε ένα δείκτη και να το ρίχνει σαν int; [Bowden] Μπορείτε να εκτυπώσετε πραγματικά ακριβώς όπως τη χρήση printf. Ας πούμε ότι έχω int y = 100. Έτσι printf (% d \ n - όπως θα πρέπει ήδη να ξέρετε - ότι εκτυπώσετε ως ένας ακέραιος, χ%. Θα εκτυπώσετε μόνο ως δεκαεξαδικό. Έτσι, ένας δείκτης δεν αποθηκεύεται ως δεκαεξαδικό, και ένας ακέραιος δεν αποθηκεύεται ως δεκαδικά. Τα πάντα είναι αποθηκευμένα ως δυαδικό. Είναι απλά ότι έχουμε την τάση να εμφανίζουν δείκτες ως δεκαεξαδικό γιατί σκεφτόμαστε τα πράγματα σε αυτές τις 4-byte μπλοκ, και διευθύνσεις μνήμης τείνουν να είναι εξοικειωμένοι. Είμαστε σαν, αν ξεκινά με bf, τότε συμβαίνει να είναι στη στοίβα. Έτσι είναι μόνο δική μας ερμηνεία των δεικτών ως δεκαεξαδικό. Εντάξει. Οι τελευταίες ερωτήσεις; Θα είμαι εδώ για λίγο μετά, αν έχετε κάτι άλλο. Και αυτό είναι το τέλος αυτού. [Φοιτητής] Yay! [Χειροκροτήματα] [CS50.TV]