[Powered by Google Translate] [ნაწილი 4 - უფრო კომფორტული] [Rob Bowden - ჰარვარდის უნივერსიტეტი] [ეს არის CS50. - CS50.TV] ჩვენ გვყავს Quiz ხვალ, იმ შემთხვევაში თუ თქვენ ბიჭები არ იცოდა, რომ. ეს ძირითადად ყველაფერზე თქვენ შეეძლო ჩანს კლასის ან უნდა გენახათ კლასში. რომელიც მოიცავს მითითებას, თუმცა ისინი ძალიან ბოლო თემას. თქვენ მაინც უნდა გვესმოდეს, მაღალი დონის მათ. რამე რომ იყო წასული მეტი კლასში თქვენ უნდა გვესმოდეს, რომ ვიქტორინა. ასე რომ თუ თქვენ გაქვთ შეკითხვები მათზე, შეგიძლიათ ვთხოვთ ახლა. მაგრამ ეს იქნება ძალიან სტუდენტი ეგიდით სხდომა, სადაც თქვენ ბიჭები კითხვის დასმის, ასე იმედია ხალხს კითხვები. ვინმეს აქვს კითხვები? დიახ. >> [სტუდენტი] შეგიძლიათ წასვლა მეტი პოინტერები ერთხელ? მე წასვლა მეტი პოინტერები. ყველა თქვენი ცვლადები აუცილებლად ცხოვრობს მეხსიერება, მაგრამ, როგორც წესი, თქვენ არ ინერვიულოთ, რომ და უბრალოდ ამბობენ x + 2 და Y + 3 და შემდგენელი იქნება გაერკვნენ, სადაც ყველაფერი ცხოვრობს თქვენთვის. ერთხელ თქვენ საქმე გჭირდებათ, ახლა თქვენ მკაფიოდ გამოყენებით იმ მეხსიერების მისამართები. ასე რომ ერთი ცვლადი იქნება მხოლოდ ოდესმე ცხოვრობს მარტოხელა მისამართი ნებისმიერ მოცემულ დროს. თუ გვინდა განვაცხადოთ, მაჩვენებელი, თუ რა ტიპის აპირებს გამოიყურებოდეს? მინდა განვაცხადო, კურსორი გვ. რას ტიპის გამოიყურებოდეს? [სტუდენტი] int * p. >> Yeah. ასე int * p. და როგორ უნდა იყოს იგი პასუხისმგებელი x? >> [სტუდენტი] Ampersand. [Bowden] ასე ampersand არის სიტყვასიტყვით მოუწოდა მისამართი ოპერატორს. ამიტომ როდესაც ვამბობ, რომ & x ის მიღების მეხსიერების მისამართი ცვლადი x. ახლა მაქვს მაჩვენებელი P, და სადმე ჩემი კოდი შემიძლია * P ან მე ვერ გამოიყენებს x და ეს იქნება ზუსტად იგივე რამ. (* P). რა არის ეს აკეთებს? რას ნიშნავს ვარსკვლავი? [სტუდენტი] ეს ნიშნავს ღირებულება იმ ეტაპზე. >> Yeah. ასე რომ, თუ დავაკვირდებით, ეს შეიძლება იყოს ძალიან სასარგებლო შესამუშაევბლად დიაგრამების როდესაც ეს პატარა ყუთი მეხსიერების x, რომელიც ხდება აქვს ღირებულება 4, მაშინ ჩვენ გვაქვს პატარა ყუთი მეხსიერების P, და ა.შ. P მიუთითებს x, ამიტომ ჩვენ მიაპყროს arrow საწყისი P to x. ასე რომ, როდესაც ჩვენ ვამბობთ * P ჩვენ ვამბობთ, წასვლა ყუთი რომ არის გვ. Star არის დაიცვას arrow და მერე რაც გაგიხარდებათ, რომ ყუთში უფლება არსებობს. ასე რომ შემიძლია ვთქვა * p = 7 და რომ წავა ყუთი რომ არის X და ცვლილება, რომელიც მას 7. ან მე შეიძლება ითქვას, int z = * P * 2; რაც გაუგებარია, რადგან ეს ვარსკვლავი, ვარსკვლავი. ერთ ვარსკვლავს dereferencing P, სხვა ვარსკვლავს გამრავლებით მიერ 2. გაითვალისწინეთ შემეძლო მხოლოდ ისევე შეცვალა * P ერთად x. თქვენ შეგიძლიათ გამოიყენოთ ისინი იგივე გზით. და შემდეგ მოგვიანებით შემიძლია აქვს P წერტილი სრულიად ახალი რამ. მე შემიძლია მხოლოდ ვთქვა, P = &z; ახლა P აღარ მიუთითებს x, ეს მიუთითებს ჩ. და ნებისმიერ დროს გავაკეთო * P ეს იგივე როგორც აკეთებს z. ასე სასარგებლო რამ შესახებ ეს ერთხელ ჩვენ ვიწყებთ მისაღებად შევიდა ფუნქციები. ეს სახის აზრი არ განაცხადოს მაჩვენებელი, რომელიც მიუთითებს რაიმე და შემდეგ, თქვენ მხოლოდ dereferencing ეს როდესაც თქვენ შეეძლო გამოყენებული ორიგინალური ცვლადი იწყება. მაგრამ როდესაც თქვენ შეღწევას ფუნქციები - ასე ვთქვათ ჩვენ გვაქვს რამდენიმე ფუნქცია, int foo, რომ იღებს მაჩვენებელი და მხოლოდ ს * p = 6; როგორც ჩვენ ვნახეთ ადრე ერთად swap, ვერ გააკეთებს ეფექტური swap და ცალკე ფუნქცია მხოლოდ გავლით რიცხვებით რადგან ყველაფერი C ყოველთვის ავლით ღირებულება. მაშინაც კი, როდესაც თქვენ ავლით პოინტერები თქვენ ავლით ღირებულება. ეს უბრალოდ ისე ხდება, რომ ეს ღირებულებები მეხსიერების მისამართები. ამიტომ როდესაც ვამბობ, რომ foo (P); მე ჩაბარების მაჩვენებელი შევიდა ფუნქცია foo და შემდეგ foo აკეთებს * p = 6; ასე რომ შიგნით რომ ფუნქცია, * P კვლავ ექვივალენტი x, მაგრამ მე მას ვერ გამოიყენებს x შიგნით რომ ფუნქცია, რადგან ეს არ scoped ფარგლებში, რომ ფუნქცია. ასე * p = 6 ეს არის ერთადერთი გზა მე შეუძლიათ ადგილობრივი ცვლადი სხვა ფუნქცია. ან, ასევე, მითითებები ერთადერთი გზა მე შეუძლიათ ადგილობრივი ცვლადი სხვა ფუნქცია. [სტუდენტი] ვთქვათ თქვენ სურდა დაბრუნების მაჩვენებელი. როგორ ზუსტად არ იცით ეს? [Bowden] დაბრუნება კურსორი როგორც რაღაც int y = 3; დაბრუნების & Y? >> [სტუდენტი] Yeah. [Bowden] Okay. თქვენ არასდროს არ უნდა ამის გაკეთება. ეს არის ცუდი. ვფიქრობ ვნახე ამ ლექციის სლაიდები თქვენ დაიწყო ვხედავთ ამ მთელი დიაგრამის მეხსიერება სადაც აქ თქვენ მოხვდით მეხსიერების მისამართი 0 და ქვევით აქ თქვენ გაქვთ მეხსიერების მისამართი 4 gigs ან 2 დან 32. ასეა, მაშინ თქვენ მოხვდით რაღაცები და რაღაცები და შემდეგ თქვენ გაქვთ თქვენი დასტის და თქვენ მოხვდით თქვენი ბევრი, რომელიც უბრალოდ დაიწყო სწავლის შესახებ, იზრდებოდა. [სტუდენტი] არ არის ბევრი ზემოთ დასტის? Yeah. ბევრი არის თავზე, არ არის ეს? >> [სტუდენტი] ისე, მან 0 თავზე. [სტუდენტი] Oh, მან 0 თავზე. >> [სტუდენტი] Oh, okay. შენიშვნა: Anywhere ერთად CS50 თქვენ აპირებს დანახვა ამ გზით. >> [სტუდენტი] Okay. უბრალოდ, როდესაც თქვენ პირველი ხედავს stacks, მოეწონა, როცა ფიქრობთ დასტის ფიქრობთ დაწყობა რამ თავზე ერთმანეთს. ამიტომ, ჩვენ გვსურს წავახალისოთ Flip ეს დაახლოებით ასე დასტის იზრდება მოსწონს დასტის ჩვეულებრივ აკეთებთ ნაცვლად დასტის ჩამოკიდებული ქვემოთ. >> [სტუდენტი] ნუ heaps ტექნიკურად იზრდებიან ძალიან, თუმცა? ეს დამოკიდებულია, რაც თქვენ გულისხმობთ იზრდებიან. დასტის და ბევრი ყოველთვის იზრდებოდნენ საპირისპირო მიმართულებით. დასტის ყოველთვის იზრდებოდა, იმ გაგებით, რომ ის იზრდებოდა მიმართ უმაღლესი მეხსიერების მისამართები, და ბევრი იზრდება ქვევით რომ ის მზარდი მიმართ ქვედა მეხსიერების მისამართები. ასე რომ ყველაზე არის 0 და ბოლოში არის მაღალი მეხსიერება მისამართები. ისინი ორივე იზრდება, მხოლოდ დაპირისპირებულ მიმართულებით. [სტუდენტი] მე მხოლოდ იმას ნიშნავდა, რომ რადგან თქვენ თქვით თქვენ დააყენა დასტის ქვედა რადგანაც როგორც ჩანს უფრო ინტუიტიური რადგან დასტის დაიწყოს ზედა ბევრი, ბევრი არის თავზე თავად ძალიან, ასე that's - >> Yeah. თქვენ ასევე ვფიქრობ ბევრი როგორც იზრდებოდა და უფრო დიდი, მაგრამ დასტის მით უმეტეს. ამიტომ დასტის არის ერთი, რომ ჩვენ სახის სურს, იზრდებოდა. მაგრამ ყველგან გადავხედავთ სხვაგვარად აპირებს ნახოთ მისამართზე 0 ზედა და უმაღლესი მეხსიერების მისამართი ბოლოში, ასე რომ ეს არის თქვენი ჩვეულებრივი ხედი მეხსიერება. გაქვთ შეკითხვა? [სტუდენტი] შეგიძლიათ გვითხრათ უფრო მეტი ბევრი? Yeah. მე მისაღებად რომ მეორე. პირველი, ბრუნდება რატომ დაბრუნების & Y არის ცუდი რამ, on დასტის გაქვთ bunch of დასტის ფარგლებში, რომელიც წარმოადგენს ყველა ფუნქციებს რომლებიც მოუწოდა. ასე იგნორირება წინა ნივთები, ზევით თქვენი დასტის ყოველთვის იქნება მთავარი ფუნქცია რადგან ეს არის ის პირველი ფუნქცია, რომელიც მიმდინარეობს მოუწოდა. და მაშინ როცა რეკავთ სხვა ფუნქცია, დასტის აპირებს იზრდება ქვევით. ასე რომ, თუ მოვუწოდებ ზოგიერთი ფუნქცია, foo, და იგი იღებს საკუთარი დასტის ჩარჩო, მას შეუძლია მოვუწოდებთ ზოგიერთი ფუნქცია, ბარი; იგი იღებს საკუთარი დასტის ჩარჩო. და ბარი შეიძლება იყოს რეკურსიული და ეს შეიძლება მოუწოდოს თავად, და ისე, რომ მეორე ზარი ბარი აპირებს საკუთარი დასტის ჩარჩო. და მერე რა მიდის ამ დასტის ფარგლებში ყველა ადგილობრივი ცვლადები და ყველა ფუნქციის არგუმენტები, რომ - ნებისმიერი რამ, რომლებიც ადგილობრივად scoped ამ ფუნქციის წასვლა ამ დასტის ფარგლებში. ასე რომ, რაც იმას ნიშნავს, როდესაც ვთქვი რაღაც ბარი არის ფუნქცია, მე უბრალოდ აპირებს გამოაცხადოს რიცხვი და შემდეგ დაბრუნდნენ მომცეთ, რომ მთელი რიცხვი. ასე რომ სად Y ცხოვრობენ? [სტუდენტი] Y ცხოვრობს ბარი. >> [Bowden] Yeah. სადღაც ამ პატარა მოედანზე მეხსიერების littler მოედანზე, რომელსაც აქვს Y მას. როდესაც მე დაბრუნებას & Y, მე დაბრუნების მომცეთ ამ პატარა ბლოკი მეხსიერება. მაგრამ შემდეგ, როდესაც ფუნქცია დააბრუნებს, მისი დასტის ჩარჩოში იღებს popped off Stack. და ამიტომ ე.წ. დასტის. ეს მოსწონს დასტის მონაცემები სტრუქტურის, თუ იცით რას რომ არის. ან თუნდაც მოსწონს Stack of უჯრები ყოველთვის მაგალითად, მთავარი აპირებს წავიდეს ქვედა, მაშინ პირველი ფუნქცია რეკავთ აპირებს წავიდეს თავზე რომ, და ვერ დავუბრუნდეთ მთავარ სანამ არ დაბრუნდება ყველა ფუნქცია, რომელიც მოუწოდა რომ უკვე განთავსებული ზევით იგი. [სტუდენტი] ასე რომ, თუ თქვენ ამაზე გავაკეთოთ დაბრუნების & Y, რომ ღირებულება შეიძლება შეიცვალოს გაფრთხილების გარეშე. დიახ, it's - >> [სტუდენტი] ეს შეიძლება იყოს ახლით. >> Yeah. ეს სრულიად - თუ თქვენ ცდილობენ და - ეს ასევე იქნება int * ბარი რადგანაც ეს დაბრუნების მაჩვენებელი, ამიტომ მისი დაბრუნების პირობა არის int *. თუ თქვენ ცდილობენ გამოიყენონ დაბრუნებული მნიშვნელობა ამ ფუნქციას, ეს გაურკვეველი ქცევა იმიტომ, რომ მაჩვენებელი მიუთითებს ცუდი მეხსიერება. >> [სტუდენტი] Okay. მერე რა, რომ, მაგალითად, თქვენ განაცხადა int * y = malloc (sizeof (int))? რომ სჯობს. დიახ. [სტუდენტი] ვისაუბრეთ იმაზე, თუ როგორ, როდესაც ჩვენ გადაიტანეთ რამ ჩვენს recycle bin ისინი რეალურად არ წაშლილია, ჩვენ უბრალოდ კარგავენ პოინტერები. ასე რომ ამ შემთხვევაში ჩვენ ფაქტობრივად წაშლას ღირებულება თუ ჯერ კიდევ არსებობს მეხსიერებაში? უმეტესწილად, ეს აპირებს კვლავ იყოს იქ. მაგრამ ვთქვათ ჩვენ მოხდეს მოვუწოდებთ ზოგიერთი სხვა ფუნქცია, baz. Baz აპირებს საკუთარი დასტის ჩარჩო აქ. ეს იქნება overwriting ყველა ამ პერსონალის, და მაშინ თუ გვიან შეეცდება და გამოიყენოთ მაჩვენებელი, შენ წინაშე, ეს არ იქნება იგივე ღირებულება. იგი აპირებს შეიცვალა მხოლოდ იმიტომ, რომ თქვენ მოუწოდა ფუნქცია baz. [სტუდენტი] მაგრამ ჩვენ არ, რომ ჩვენ მაინც 3? [Bowden] ყველა ალბათობა, თქვენ აკეთებთ. მაგრამ ვერ დაეყრდნონ, რომ. C უბრალოდ ამბობს გაურკვეველი ქცევა. [სტუდენტი] ოჰ, ეს იმას. Okay. ასე რომ, როდესაც თქვენ გინდათ დაბრუნების მაჩვენებელი, ეს არის სადაც malloc მოდის გამოიყენება. მე წერა რეალურად მხოლოდ დაბრუნების malloc (3 * sizeof (int)). ჩვენ წავიდეთ მეტი malloc მეტი მეორე, მაგრამ იდეა malloc არის ყველა თქვენი ადგილობრივი ცვლადები ყოველთვის გაგრძელდება Stack. არაფერი რომ malloced გრძელდება ბევრი იქნება, და ეს სამუდამოდ და ყოველთვის იქნება ბევრი სანამ თქვენ მკაფიოდ გასათავისუფლებლად იგი. ასე რომ, ეს იმას ნიშნავს, რომ როდესაც თქვენ malloc რაღაც, ის აპირებს გადარჩება შემდეგ ფუნქცია დააბრუნებს. [სტუდენტი] უნდა ეს გადარჩება შემდეგ პროგრამა აჩერებს გაშვებული? >> პოსტები Okay, ასე რომ იქნება იქ, სანამ პროგრამა ყველა გზა გაკეთდეს გაშვებული. >> დიახ. ჩვენ შეგვიძლია წავიდეთ მეტი დეტალები, თუ რა ხდება, როდესაც პროგრამა აჩერებს გაშვებული. ალბათ უნდა მაგონებს, მაგრამ ეს ცალკე რამ მთლიანად. [სტუდენტი] ასე malloc ქმნის მაჩვენებელი? >> Yeah. Malloc - >> [სტუდენტი] ვფიქრობ malloc აღნიშვნას ბლოკი მეხსიერება რომ მომცეთ შეგიძლიათ გამოიყენოთ. [Bowden] მინდა რომ დიაგრამაზე ერთხელ. >> [სტუდენტი] ასე რომ, ეს ფუნქცია მუშაობს, თუმცა? [სტუდენტი] ჰო, malloc აღნიშვნას ბლოკი მეხსიერება, რომელიც შეგიძლიათ გამოიყენოთ, და მაშინ ის დააბრუნებს მისამართი პირველი ბლოკი, რომ მეხსიერებაში. [Bowden] Yeah. ასე რომ, როდესაც თქვენ malloc, თქვენ grabbing ზოგიერთი ბლოკი მეხსიერება რომ ამჟამად ბევრი. თუ ბევრი მცირეა, მაშინ ბევრი უბრალოდ აპირებს იზრდება, და ეს იზრდება ამ მიმართულებით. ასე ვთქვათ ბევრი მცირეა. მაშინ ის შესახებ გაიზარდოს ცოტა და დააბრუნოს მომცეთ ამ ბლოკში რომ მხოლოდ გაიზარდა. როცა თავისუფალი პერსონალი, თქვენ უფრო ოთახში ბევრი, ასეა, მაშინ მოგვიანებით დარეკვა malloc შეგიძლიათ reuse რომ მეხსიერება, რომ თქვენ ადრე გაათავისუფლეს. მთავარია შესახებ malloc და თავისუფალი არის ის, რომ გაძლევთ სრულ კონტროლს მეტი ცხოვრებისეული ამ მეხსიერების ბლოკები. გლობალური ცვლადები ყოველთვის ცოცხალია. ლოკალური ცვლადები ცოცხალი მათ ფარგლებს. როგორც კი წავიდეთ წარსულში Curly გაუწიოს, ადგილობრივი ცვლადები მკვდარი. Malloced მეხსიერების ცოცხალია როდესაც გსურთ, რომ იყოს ცოცხალი და მაშინ გამოვიდა, როცა ვამბობ, რომ უნდა განთავისუფლდეს. ეს ის რეალურად მხოლოდ 3 ტიპის მეხსიერება, ნამდვილად. არსებობს ავტომატური მეხსიერების მართვა, რომელიც დასტის. რამ ხდება თქვენთვის ავტომატურად. როცა ამბობენ int x, მეხსიერების გამოყოფილი int x. როდესაც x გადის ფარგლებს, მეხსიერების reclaimed ამისთვის x. მაშინ არსებობს დინამიური მეხსიერების მართვა, რაც malloc არის, რაც როდესაც თქვენ კონტროლი. თქვენ დინამიურად გადასაწყვეტია, როდის მეხსიერების უნდა და არ უნდა გამოყო. და მაშინ არსებობს სტატიკური, რომელიც მხოლოდ იმას ნიშნავს, რომ ის ცხოვრობს სამუდამოდ, რაც გლობალური ცვლადები არიან. ისინი უბრალოდ ყოველთვის მეხსიერებაში. კითხვები? [სტუდენტი] შეგიძლიათ განსაზღვროს ბლოკი უბრალოდ გამოყენებით Curly braces მაგრამ არ მქონე აქვს თუ განაცხადი ან ხოლო განაცხადი ან არაფერი რომ? თქვენ შეგიძლიათ განსაზღვროს ბლოკი როგორც ფუნქცია, მაგრამ რომ აქვს Curly braces ძალიან. [სტუდენტი] ასე რომ თქვენ არა მხოლოდ აქვს, როგორიც შემთხვევითი წყვილი Curly braces თქვენს კოდი რომ აქვს ადგილობრივი ცვლადები? >> დიახ, შეგიძლიათ. შიგნით int ბარი ჩვენ შეგვეძლო {int y = 3;}. რომ უნდა იყოს უფლება აქ. მაგრამ ეს მთლიანად განსაზღვრავს ფარგლებს int y. ამის შემდეგ მეორე Curly გაუწიოს, Y არ გამოიყენება უქმნით. თქვენ თითქმის არასოდეს გავაკეთებთ, თუმცა. დავუბრუნდეთ რა ხდება, როდესაც პროგრამა დამთავრდა, არსებობს სახის misconception / ნახევარი ტყუილი, რომ ვაძლევთ, რათა მხოლოდ მიიღოს რამ ადვილია. ჩვენ გითხრათ, რომ როდესაც თქვენ გამოყოს მეხსიერება თქვენ გამოყოფის ზოგიერთი ბლოკი RAM რომ ცვლადი. მაგრამ თქვენ არ რეალურად პირდაპირ ეხება RAM ოდესმე თქვენს პროგრამებში. თუ ფიქრობთ, ეს, რა მიიპყრო - და ფაქტობრივად, თუ თქვენ გავლა in GDB დაინახავთ იგივე. მიუხედავად რამდენჯერ თქვენ აწარმოებს თქვენი პროგრამის ან რა პროგრამა თქვენ გაშვებული, დასტის ყოველთვის იწყებს - თქვენ ყოველთვის აპირებს ვხედავ ცვლადებს გარშემო მისამართი oxbffff რაღაც. ეს, როგორც წესი, სადღაც, რომ რეგიონში. მაგრამ როგორ შეიძლება 2 პროგრამები შესაძლოა აქვს მითითებას იგივე მეხსიერება? [სტუდენტი] არსებობს რამდენიმე თვითნებური დანიშნულება აქ oxbfff უნდა იყოს RAM რომ შეიძლება რეალურად იყოს სხვადასხვა ადგილებში დამოკიდებულია როდესაც ფუნქციის ეწოდა. Yeah. ტერმინი არის ვირტუალური მეხსიერება. იდეა ისაა, რომ თითოეული პროცესი, თითოეული პროგრამა, რომელიც არის გაშვებული თქვენს კომპიუტერში აქვს საკუთარი - მოდით ვივარაუდოთ, 32 ბიტი - სრულიად დამოუკიდებელი მისამართი სივრცეში. ეს არის მისამართი სივრცეში. აქვს საკუთარი სრულიად დამოუკიდებელი 4 გბ გამოიყენოს. ასე რომ, თუ თქვენ აწარმოებს 2 პროგრამები ერთდროულად, ამ პროგრამის ხედავს 4 გბ, თვით ამ პროგრამის ხედავს 4 გბ, თვით და ეს შეუძლებელია ამ პროგრამის dereference მაჩვენებელი და დასრულდება მდე მეხსიერების ამ პროგრამის. და რა ვირტუალური მეხსიერების არის რუკების საწყისი პროცესების მისამართი სივრცეში ნამდვილ რამ on RAM. ამიტომ მდე თქვენი ოპერაციული სისტემა იცოდეს, რომ, hey, როცა ამ ბიჭს dereferences მაჩვენებელი oxbfff, რომ ნამდვილად ნიშნავს რომ მას სურს RAM byte 1000, ხოლო თუ ამ პროგრამის dereferences oxbfff, მას მართლაც სურს RAM byte 10000. ეს შეიძლება იყოს თვითნებურად შორს გარდა. ეს არის კიდევ ნამდვილი რამ ერთ პროცესების მისამართი სივრცეში. ასე რომ, როგორც ეს ხედავს ყველა 4 გბ, არამედ ვთქვათ - [სტუდენტი] არა თითოეული პროცესი - ვთქვათ თქვენ გაქვთ კომპიუტერი მხოლოდ 4 გბ ოპერატიული მეხსიერება. ამჯამად თითოეული პროცესი მთლიანად ჩანს 4 გიგაბაიტი? >> დიახ. მაგრამ 4 გიგაბაიტი ის ხედავს არის ტყუილი. უბრალოდ ეს მიაჩნია მას ყველა ამ მეხსიერების რადგან ეს არ ვიცი არც ერთი სხვა პროცესი არსებობს. ეს იქნება მხოლოდ იმდენი მეხსიერება, როგორც ეს რეალურად სჭირდება. ოპერაციული სისტემა დათმობას არ აპირებს მეხსიერება ამ პროცესში თუ ეს არ გამოყენებით ნებისმიერი მეხსიერების ამ მთელი რეგიონისთვის. ის დათმობას არ აპირებს იგი მეხსიერებაში, რომ რეგიონში. მაგრამ იდეა ისაა, რომ - ვცდილობ ვფიქრობ - მე ვერ ვფიქრობ ანალოგია. ანალოგიების რთულია. ერთი საკითხი ვირტუალური მეხსიერების ან ერთი რამ ეს გადაჭრის ის არის, რომ პროცესი უნდა მთლიანად იცის ერთმანეთს. და ასე რომ თქვენ შეგიძლიათ დაწეროთ ნებისმიერი პროგრამა, რომელიც მხოლოდ dereferences ნებისმიერი მაჩვენებელი, მინდა უბრალოდ წერენ პროგრამა, რომელიც ამბობს * (ox1234), და ეს dereferencing მეხსიერების მისამართი 1234. მაგრამ ეს მდე ოპერაციული სისტემის შემდეგ თარგმნოს რა 1234 საშუალებებით. ასე რომ, თუ 1234 მოხდება იქნება სწორი მეხსიერების მისამართი ამ პროცესში, მოსწონს ეს on დასტის ან რამე, მაშინ ეს დაბრუნდება ღირებულება რომ მეხსიერების მისამართი რამდენადაც პროცესი იცის. მაგრამ თუ 1234 არ არის სწორი მისამართი, როგორც ეს ხდება მიწის ზოგიერთ პატარა ნაჭერი მეხსიერება აქ რომ სცილდება დასტის და მის ფარგლებს გარეთ ბევრი და თქვენ ნამდვილად არ გამოიყენება, რომ, მაშინ, რომ როდესაც თქვენ რამ, როგორიცაა segfaults იმიტომ, რომ თქვენ შეხება მეხსიერების, რომ თქვენ არ უნდა ეხება. ეს არის ასევე ჭეშმარიტი - 32-bit სისტემა, 32 ბიტი ნიშნავს გაქვთ 32 ბიტი, განისაზღვროს მეხსიერების მისამართზე. ეს რატომ მითითებები 8 ბაიტი, რადგან 32 ბიტი არის 8 ბაიტი - ან 4 ბაიტი. მითითებები 4 ბაიტი. ასე რომ, როდესაც თქვენ ხედავთ, მაჩვენებელი, როგორიცაა oxbfffff, რომ არის - ფარგლებში ნებისმიერ მოცემულ პროგრამაში შეგიძლიათ უბრალოდ აშენება ნებისმიერი თვითნებური მაჩვენებელი, ყველგან საწყისი ox0 to ox 8 f's - ffffffff. [სტუდენტი] არ ამბობენ ისინი 4 ბაიტი? >> Yeah. [სტუდენტი] თითოეული byte ექნება - >> [Bowden] თექვსმეტობითი. თექვსმეტობითი - 5, 6, 7, 8. ამიტომ პოინტერები თქვენ აპირებს ყოველთვის ვხედავთ თექვსმეტობითი. უბრალოდ, რა არის ჩვენი დაალაგეთ პოინტერები. ყოველ 2 ციფრით თექვსმეტობითი არის 1 ბაიტი. ასე იქნება 8 თექვსმეტობითი ციფრები 4 ბაიტი. ამიტომ თითოეული კურსორი on 32-bit სისტემა იქნება 4 ბაიტი, რაც იმას ნიშნავს, რომ თქვენს პროცესში შეგიძლიათ აშენება ნებისმიერი თვითნებური 4 ბაიტი და მიიღოს მაჩვენებელი გარეთ, რაც იმას ნიშნავს, რომ რამდენადაც ეს იცის, მას შეუძლია მიმართოს მთელი 2 დან 32 ბაიტი მეხსიერება. მიუხედავად იმისა, რომ ნამდვილად არ აქვს დაშვება, რომ, მაშინაც კი, თუ თქვენს კომპიუტერს აქვს მხოლოდ 512 მბ, ეს ფიქრობს, მას, რომ ბევრი რამ მეხსიერებაში. და საოპერაციო სისტემის smart საკმარისი, რომ იგი მხოლოდ გამოყოფს, რაც თქვენ რეალურად სჭირდება. იგი არ უბრალოდ, OH, ახალ პროცესს: 4 gigs. Yeah. >> [სტუდენტი] რას ნიშნავს ox? რატომ წერთ ამას? უბრალოდ სიმბოლო თექვსმეტობითი. როდესაც ხედავთ ხმების იწყება ox, თანმიმდევრული რამ თექვსმეტობითი. [სტუდენტი] იყავით ხსნიდა შესახებ, თუ რა ხდება, როდესაც პროგრამა დასრულდება. >> დიახ. რა ხდება, როდესაც პროგრამა დამთავრდა არის ოპერაციული სისტემა უბრალოდ შლის mappings, რომ მას ამ მისამართები, და ამით ყველაფერი მთავრდება. ოპერაციული სისტემა შეიძლება ახლა მხოლოდ მისცეს, რომ მეხსიერების სხვა პროგრამა გამოიყენოს. [სტუდენტი] Okay. ასე რომ, როდესაც თქვენ გამოყოფს რაღაც ბევრი ან დასტის ან გლობალური ცვლადები ან არაფერი, ისინი ყველა უბრალოდ გაქრება, როგორც კი პროგრამა დასრულდება რადგან ოპერაციული სისტემა არის უფასო მისცეს, რომ მეხსიერების რაიმე სხვა პროცესი. [სტუდენტი] მიუხედავად იმისა, რომ არსებობს ალბათ მაინც ღირებულებების დაწერილი? >> Yeah. ღირებულებები სავარაუდოდ ჯერ კიდევ არსებობს. უბრალოდ ეს იქნება რთული მისაღებად მათ. ეს ბევრად უფრო რთული მისაღებად მათ ვიდრე მისაღებად საათზე წაშლილი ფაილი რადგან წაშლილი ფაილის სახის ზის იქ დიდი ხნის განმავლობაში და ხისტ დისკზე არის ბევრი დიდია. ამიტომ აპირებს გადავაწერო სხვადასხვა კუთხეში მეხსიერება სანამ ეს მოხდება გადავაწერო ბლოკი მეხსიერება, რომ ფაილი იზრდებოდნენ. მაგრამ მთავარ მეხსიერება, RAM, თქვენ ციკლის მეშვეობით ბევრი უფრო სწრაფად, ამიტომ აპირებს ძალიან სწრაფად იყოს ახლით. კითხვები ამ ან სხვა რამეზე? [სტუდენტი] მაქვს შეკითხვები სხვადასხვა თემაზე. >> Okay. ვინმეს აქვს კითხვები ამ? Okay. სხვადასხვა თემას. >> [სტუდენტი] Okay. მივდიოდი მეშვეობით ზოგიერთი პრაქტიკა ტესტები, და ერთ მათგანს იყო ლაპარაკი sizeof და ღირებულება, რომ ის დააბრუნებს ან სხვადასხვა ცვლადი ტიპები. >> დიახ. და ეს აღნიშნა, რომ ორივე int და ხანგრძლივი ორივე დაბრუნების 4, ამიტომ ისინი ორივე 4 ბაიტი ხანგრძლივი. არსებობს თუ არა განსხვავება int და ხანგრძლივი, თუ იგივე? დიახ, არსებობს განსხვავება. C სტანდარტი - მე ალბათ აპირებს mess up. C სტანდარტი ისევე რა არის C, ოფიციალური დოკუმენტაცია C. ეს არის ის, რაც ნათქვამია. ამიტომ C სტანდარტული უბრალოდ ამბობს, რომ char სამუდამოდ და ყოველთვის იქნება 1 ბაიტი. ყველაფერი ამის შემდეგ - მოკლე ყოველთვის მხოლოდ განსაზღვრული როგორც მეტია ან ტოლია char. ეს შეიძლება იყოს მკაცრად მეტი, მაგრამ არა დადებითი. Int მხოლოდ განსაზღვრული როგორც მეტია ან ტოლია მოკლე. და ხანგრძლივი მხოლოდ განსაზღვრული როგორც მეტია ან ტოლია int. და ხანგრძლივი ხანგრძლივი მეტია ან ტოლია ხანგრძლივი. ასე რომ ერთადერთი C სტანდარტი საზღვრავს არის ნათესავი რიგი ყველაფერი. ფაქტობრივი რაოდენობის მეხსიერება, რაც რამ დასჭირდეს ზოგადად მდე განხორციელების, მაგრამ კარგად განსაზღვრული ამ ეტაპზე. >> [სტუდენტი] Okay. ასე რომ შორტები თითქმის ყოველთვის იქნება 2 ბაიტი. Ints თითქმის ყოველთვის იქნება 4 ბაიტი. დიდხანს longs თითქმის ყოველთვის იქნება 8 ბაიტი. და longs, ეს დამოკიდებულია თუ არა თქვენ იყენებთ 32-bit ან 64-bit სისტემა. ასე ხანგრძლივი აპირებს შეესაბამება ტიპის სისტემა. თუ თქვენ იყენებთ 32-bit სისტემის მსგავსად ელექტრო მოწყობილობების, ეს იქნება 4 ბაიტი. თუ თქვენ გამოყენებით 64-bit, როგორიც ბევრი ბოლო კომპიუტერები, ეს იქნება 8 ბაიტი. Ints თითქმის ყოველთვის 4 ბაიტი ამ ეტაპზე. დიდხანს longs თითქმის ყოველთვის 8 ბაიტი. წარსულში, ints გამოყენებული იყოს მხოლოდ 2 ბაიტს. მაგრამ შეამჩნია, რომ ეს სრულიად აკმაყოფილებს ყველა ამ ურთიერთობების მეტია და ტოლია. ცოტა ხნის სრულიად დასაშვებია იყოს იგივე ზომა, როგორც მთელი რიცხვი, და ასევე უფლება აქვთ იგივე ზომა, როგორც ხანგრძლივი ხანგრძლივი. და ეს ასე მოხდება, იყოს, რომ 99,999% სისტემების, ეს იქნება ტოლი ან int ან ხანგრძლივი ხანგრძლივი. უბრალოდ დამოკიდებულია 32-bit ან 64-bit. >> [სტუდენტი] Okay. In მოძრავი, თუ როგორ არის ათობითი წერტილი დანიშნული თვალსაზრისით ბიტი? ისევე როგორც ორობითი? >> Yeah. თქვენ არ უნდა იცოდეთ, რომ CS50. თქვენ კი არ სწავლობენ, რომ 61. თქვენ არ ვისწავლოთ, რომ მართლაც რაიმე რა თქმა უნდა. უბრალოდ წარმომადგენლობა. მე დაგვავიწყდეს ზუსტი bit allotments. იდეა მცურავი წერტილი არის ის, რომ თქვენ გამოყოფს კონკრეტული რაოდენობის ბიტი წარმოადგენს - ძირითადად, ყველაფერი სამეცნიერო ნოტაცია. ასე, რომ თქვენ გამოყოფს კონკრეტული რაოდენობის ბიტი წარმოადგენს ნომერი თავად მოსწონს 1,2345. მე შემიძლია არასოდეს წარმოადგენენ ხმების მეტი ციფრები, ვიდრე 5. მაშინ თქვენ ასევე გამოყოს კონკრეტული რაოდენობის ბიტი ისე, რომ იგი აპირებს იყოს თქვენ შეგიძლიათ მხოლოდ ახვიდეთ გარკვეული რაოდენობა, როგორიცაა რომ უმსხვილეს მაჩვენებლებით შეგიძლიათ, და თქვენ მხოლოდ იქ შეგვიძლია ქვემოთ გარკვეული მაჩვენებლებით, მინდა, რომ ყველაზე პატარა მაჩვენებლებით შეგიძლიათ. მე არ მახსოვს ზუსტი გზა ბიტი გვაკისრია ყველა ამ ფასეულობების, მაგრამ გარკვეული რაოდენობის ბიტი ეძღვნება 1,2345, კიდევ ერთი გარკვეული რაოდენობის ბიტი ეძღვნება მაჩვენებლებით, და ეს შესაძლებელია მხოლოდ წარმოადგენენ მაჩვენებლებით გარკვეული ზომით. [სტუდენტი] და ორმაგი? არის ის, რომ მოსწონს დამატებითი ხანგრძლივი float? >> Yeah. ეს იგივე როგორც float გარდა ახლა თქვენ იყენებთ 8 ბაიტი ნაცვლად 4 ბაიტი. ახლა თქვენ შეძლებთ გამოიყენოთ 9 ციფრისგან ან 10 ნიშნა, და ამ შეძლებს ახვიდეთ 300 ნაცვლად 100. >> [სტუდენტი] Okay. და მოძრავი ასევე 4 ბაიტი. >> დიახ. ისე, კიდევ ერთხელ, ალბათ დამოკიდებულია საერთო საერთო შესრულების, მაგრამ მოძრავი არიან 4 ბაიტი, ორადგილიანი არიან 8. ორადგილიანი ეწოდება ორმაგი რადგან ისინი ორმაგი ზომის მოძრავი. [სტუდენტი] Okay. და თუ არიან ორმაგი ორჯერ? >> არ არსებობს. ვფიქრობ - >> [სტუდენტი] მსგავსად ხანგრძლივი longs? >> Yeah. მე ასე არ ვფიქრობ. დიახ. [სტუდენტი] On შარშანდელი ტესტი იყო შეკითხვა მთავარი ფუნქცია მქონე ნაწილი იყოს თქვენი პროგრამა. პასუხი იყო, რომ ეს არ უნდა იყოს ნაწილი თქვენი პროგრამა. რა სიტუაციაში? რაც ვნახე. [Bowden] როგორც ჩანს - >> [სტუდენტი] რა სიტუაციაში? გაქვთ პრობლემა? >> [სტუდენტი] ჰო, მე შემიძლია ცალსახად დახევის it up. იგი არ უნდა იყოს, ტექნიკურად, მაგრამ ძირითადად ეს იქნება. [სტუდენტი] ვნახე ერთი განსხვავებული წლის. თითქოს True ან False: მოქმედებს - >> Oh,. გ ფაილი? [სტუდენტი] ნებისმიერი. გ ფაილი უნდა ჰქონდეს - [როგორც საუბრისას კიდევ ერთხელ - გაუგებარია] Okay. ასე რომ ცალკე. . გ ფაილი უბრალოდ სჭირდება შეიცავდეს ფუნქციები. შეგიძლიათ კომპილაციის ფაილის შევიდა მანქანა კოდი, ორობითი, რასაც, მის გარეშე ყოფნა შესრულებადი ამჟამად. ძალაში შესრულებადი უნდა ჰქონდეს ძირითად ფუნქციას. თქვენ შეგიძლიათ დაწეროთ 100 ფუნქციების 1 ფაილი მაგრამ არა ძირითადი და შემდეგ ადგენენ, რომ ქვემოთ ორობითი, შემდეგ ვწერთ სხვა ფაილი, რომელიც მხოლოდ ძირითად, არამედ ის მოუწოდებს bunch ამ ფუნქციების ამ ორობითი ფაილი აქ. და ამრიგად, როდესაც თქვენ მიღების შესრულებადი არის ის, რაც linker აკეთებს იგი აერთიანებს ამ 2 ორობითი ფაილს შესრულებადი. ასე რომ. გ ფაილი არ უნდა მთავარი ფუნქცია იყო. და დიდი კოდი ბაზების დაინახავთ ათასობით. გ ფაილი და 1 მთავარი ფაილი. სხვა კითხვები? [სტუდენტი] იყო სხვა საკითხია. მისი თქმით მიიღოს არის შემდგენელი. True ან ყალბი? და პასუხი იყო ყალბი, და მივხვდი, რატომ არ მოსწონს Clang. მაგრამ, ჩვენ მოვუწოდებთ მიიღოს თუ არა? ჩადება ძირითადად მხოლოდ - მე ვხედავ, ზუსტად რა ის მოუწოდებს მას. მაგრამ ეს მხოლოდ ეშვება ბრძანებები. ჩადება. შემიძლია დახევის ეს ყველაფერი. Yeah. Oh, yeah. ჩადება ასევე აკეთებს, რომ. ეს ამბობს მიზნით კომუნალური არის, რათა დადგინდეს ავტომატურად რომელიც ცალი დიდი პროგრამა საჭიროებს recompiled და გასცემს ბრძანებას recompile მათ. შეგიძლიათ გააკეთოთ მიიღოს ფაილი, რომელიც აბსოლუტურად უზარმაზარი. ჩადება უყურებს დრო მარკების ფაილი და, როგორც ჩვენ დაწყებამდე განაცხადა, შეგიძლიათ კომპილაციის ინდივიდუალური ფაილი down, და ეს არ სანამ თქვენ მიიღებთ linker რომ ისინი ერთად შევიდა შესრულებადი. ასე რომ, თუ თქვენ გაქვთ 10 სხვადასხვა ფაილები და თქვენ ცვლილების 1 მათგანი, მაშინ რა მარკა აპირებს მხოლოდ recompile რომ 1 ფაილის და შემდეგ relink ყველაფერი ერთად. მაგრამ ეს ბევრად dumber ვიდრე რომ. ეს თქვენი გადასაწყვეტია მთლიანად განმარტავენ, რომ არის ის, რაც უნდა აკეთებს. ეს იყოს გააჩნია უნარი აღიარებს ამ დროის შტამპი პერსონალის, მაგრამ თქვენ შეგიძლიათ დაწეროთ მარკა ფაილის არაფერს. თქვენ შეგიძლიათ დაწეროთ მიიღოს ფაილი ისე, რომ როდესაც თქვენ ტიპი იყოს იგი უბრალოდ CD-ს სხვა დირექტორია. მე მიღების იმედგაცრუებული რადგანაც მე Tack ყველაფერი შიგნით ჩემი ელექტრო მოწყობილობების და მაშინ მე PDF საწყისი Mac. ამიტომ მე წასვლა Finder და შემიძლია წადი, სერვერთან დაკავშირება, და სერვერზე მე ვუკავშირდები არის ჩემი ელექტრო მოწყობილობების, და მერე გახსენით PDF რომ იღებს მიერ შედგენილი ლატექსის. მაგრამ მე არც იმედგაცრუებული, რადგან თითოეული დროს მე საჭირო ამოცნობა PDF, მომიწია კოპირება კონკრეტული დირექტორია, რომ იგი შესაძლოა შედიხართ და ეს მიღების უსიამოვნოს. ასე რომ ნაცვლად დავწერე მარკა ფაილი, რომელშიც თქვენ უნდა განისაზღვროს, თუ როგორ იგი ქმნის რამ. როგორ გახდით ამ არის PDF ლატექსის. ისევე, როგორც ნებისმიერი სხვა მარკა ფაილი - ან მე ვფიქრობ თქვენ არ მინახავს მარკა ფაილი მაგრამ გვაქვს ელექტრო გლობალური მარკა ფაილი, უბრალოდ ამბობს, თუ თქვენ შედგენის C ფაილი, გამოიყენოთ Clang. და ა.შ. აქ ჩემი მარკა ფაილი, მე ვამბობ, ამ ფაილის თქვენ აპირებს გვინდა კომპილირდება ერთად PDF ლატექსის. და ამიტომ PDF ლატექსის რომ აკეთებს შედგენა. ჩადება არ არის შედგენა. უბრალოდ გაშვებული ეს ბრძანებები დადგენილი თანმიმდევრობით I მითითებული. ასე რომ ის მუშაობს PDF ლატექსის, მას აკოპირებს მას დირექტორია მინდა მას იყოს დაკოპირებული, ეს CD-ს დირექტორიაში და არ სხვა რამ, მაგრამ ყველა ეს იმას არ არის აღიარონ როდესაც ფაილის ცვლილებები, და თუ ეს ცვლილებები, მაშინ იგი მიიღებს ბრძანებები, რომ ის უნდა აწარმოებს როდესაც ფაილი ცვლილებები. >> [სტუდენტი] Okay. მე არ ვიცი სად გლობალური მარკა ფაილი ჩემთვის შეამოწმეთ იგი out. გაქვთ სხვა კითხვები? არაფერს წარსულში ტესტებში? ნებისმიერი მაჩვენებელი რამ? არსებობს დახვეწილი რამ ერთად პოინტერები მოსწონს - მე არ ვაპირებ შევძლოთ Quiz საკითხი მას - მაგრამ ისევე, როგორც ამ სახის რამ. დარწმუნდით, რომ თქვენ გესმით, რომ როდესაც ვამბობ, რომ int * x * Y - ეს არ არის ზუსტად არაფერი აქ, ვფიქრობ. მაგრამ მოსწონს * x * Y, ეს ის 2 ცვლადები, რომლებიც Stack. როდესაც ვამბობ x = malloc (sizeof (int)), x კვლავ ცვლადი on დასტის, malloc არის ზოგიერთი ბლოკის დასრულდა ბევრი და ჩვენ მქონე x წერტილი ბევრი. ასე რომ რაღაც დასტის მიუთითებს ბევრი. როდესაც თქვენ malloc არაფერი, თქვენ აუცილებლად შენახვა ეს შიგნით მაჩვენებელი. ასე რომ კურსორი არის დასტის, malloced ბლოკი არის ბევრი. ბევრი ხალხი დაბნეული და აცხადებენ int * x = malloc; x არის ბევრი. პოსტები რა x მიუთითებს არის ბევრი. x თავად არის დასტის, თუ სხვადსხვა მიზეზის გამო თქვენ არ x იყოს გლობალური ცვლადი, ამ შემთხვევაში ხდება, რომ კიდევ ერთ რეგიონში მეხსიერება. ასე შენახვა ტრეკზე, ეს ყუთი და arrow დიაგრამების საკმაოდ საერთოა ვიქტორინა. ან თუ არა ინტელექტუალური 0, ეს იქნება ვიქტორინა 1. თქვენ უნდა იცოდეს, ყველა ეს, ნაბიჯები შედგენა მას შემდეგ, რაც თქვენ გქონდათ უპასუხოს კითხვებს იმ. დიახ. [სტუდენტი] ვერ ჩვენ მივდივართ იმ ნაბიჯების - >> დარწმუნებული. სანამ ნაბიჯები და შედგენა გვაქვს preprocessing, შედგენა, იკრიბებიან, და აკავშირებს. Preprocessing. რას აკეთებთ? ეს არის ყველაზე იოლი ნაბიჯი - კარგად, არ მოსწონს - ეს არ ნიშნავს, რომ ეს უნდა იყოს აშკარა, მაგრამ ეს იოლი ნაბიჯი. თქვენ ბიჭები შეეძლო განეხორციელებინა იგი თქუენგან. Yeah. [სტუდენტი] Take რაც თქვენ თქვენი მოიცავს მოსწონს ეს და ის ასლი და შემდეგ ასევე განსაზღვრავს. იგი ეძებს რამ, როგორიცაა # include და # განსაზღვრავს, და ეს მხოლოდ ასლები და პასტები რა იმ რეალურად ნიშნავს. ასე რომ, როდესაც თქვენ ამბობთ # მოიცავს cs50.h, preprocessor არის კოპირება და pasting cs50.h შევიდა, რომ ხაზი. როცა ამბობენ, # define x იყოს 4, preprocessor გადის მთელი პროგრამა და ცვლის ყველა ინსტანციის x ერთად 4. ამიტომ preprocessor იღებს მოქმედებს C ფაილი და შედეგები ძალაში C ფაილი აქ რამ გადაწერა და pasted. ახლა შედგენა. რას აკეთებთ? [სტუდენტი] ეს მიემართება C-დან ორობითი. [Bowden] იგი არ წავიდეთ ყველა გზა ორობითი. [სტუდენტი], რათა მანქანა კოდი მაშინ? >> ეს არ მანქანა კოდი. [სტუდენტი] ასამბლეის? >> ასამბლეის. ეს ღებულობენ ასამბლეის სანამ მიდის ყველა გზა C კოდი, და საუკეთესო ენებზე რაღაც მოსწონს ეს. Pick ნებისმიერი მაღალი დონის ენა და, თუ თქვენ აპირებს მისი კომპილირება, ეს სავარაუდოდ კომპილაციის წელს ნაბიჯები. პირველი ის აპირებს კომპილაციის Python to C, მაშინ იგი აპირებს კომპილაციის C შეკრებისა, და მაშინ ასამბლეის აპირებს მისაღებად ითარგმნა ენაზე ორობითი. ამიტომ შედგენას აპირებს მოუტანს იგი C შეკრებისა. სიტყვა შედგენა ჩვეულებრივ გულისხმობს იგი მაღალ დონეზე to ქვედა დონის პროგრამირების ენაზე. ასე რომ, ეს მხოლოდ ნაბიჯი შედგენაში, სადაც თქვენ იწყება მაღალი დონის ენა და დასრულდება up in დაბალი დონის ენა, და ამიტომაც ნაბიჯი ეწოდება შედგენა. [სტუდენტი] დროს შედგენა, ვთქვათ, რომ თქვენ გავაკეთეთ # მოიცავს cs50.h. უილ შემდგენელი recompile cs50.h, როგორიცაა ფუნქციებს, რომლებიც იქ, და თარგმნოს რომ შევიდა ასამბლეის კოდი ისევე, ან იქნება ეს დააკოპირეთ და ჩასვით ის, რაც უკვე წინასწარ ასამბლეის? cs50.h იქნება საკმაოდ ბევრი არასოდეს დასრულდება up in ასამბლეის. პერსონალის მოსწონს ფუნქცია პროტოტიპები და სიტუაცია უბრალოდ თქვენ ფრთხილად. იგი გარანტიას, რომ შემდგენელი შეგიძლიათ შეამოწმოთ რამ, როგორიცაა თქვენ მოუწოდებდა ფუნქციები უფლების მქონე დაბრუნების ტიპის და უფლება არგუმენტები და პერსონალი. ამიტომ cs50.h იქნება preprocessed შევიდა ფაილი, ხოლო შემდეგ, როდესაც ის შედგენა ის ძირითადად დააგდეს დაშორებით მას შემდეგ, რაც ხდის დარწმუნებული, რომ ყველაფერი მიმდინარეობს მოუწოდა სწორად. მაგრამ ფუნქციები განისაზღვრება CS50 ბიბლიოთეკა, რომლებიც დამოუკიდებლად cs50.h, იმ არ იქნება ცალკე შედგენილი. რომ რეალურად მოდის ქვემოთ აკავშირებს ნაბიჯი, ამიტომ ჩვენ მისაღებად რომ მეორე. მაგრამ პირველი, რასაც იკრიბებიან? [სტუდენტი] ასამბლეის ორობითი? >> Yeah. იკრიბებიან. ჩვენ არ ეძახით შედგენა რადგან ასამბლეა საკმაოდ ბევრი სუფთა თარგმანი ორობითი. არსებობს ძალიან მცირე ლოგიკით მიდის საწყისი ასამბლეის ორობითი. უბრალოდ მინდა ეძებს up in მაგიდა, OH, ჩვენ გვაქვს ამ ინსტრუქციით; რაც შეესაბამება ორობითი 01110. და ა.შ. ფაილი, რომელიც იკრიბება ზოგადად მასალები არიან. O ფაილი. და. O ფაილი რასაც ვამბობდით ადრე, როგორ ფაილი არ უნდა მთავარი ფუნქცია. ნებისმიერი ფაილი შეიძლება იყოს შედგენილი ქვემოთ. O ფაილი რადგან ეს სწორი C ფაილი. ეს შეიძლება იყოს შედგენილი ქვემოთ. O. ახლა აკავშირებს არის ის, რაც რეალურად მოაქვს bunch of. O ფაილი და მოაქვს მათ შესრულებადი. და მერე რა აკავშირებს არ არის შეგიძლიათ წარმოიდგინოთ, რომ CS50 ბიბლიოთეკა. O ფაილი. ეს უკვე შედგენილი ორობითი ფაილი. და ამრიგად, როდესაც თქვენ კომპილაციის თქვენი ფაილი, თქვენი hello.c, რომელიც მოუწოდებს GetString, hello.c იღებს შედგენილი ქვემოთ hello.o, hello.o ახლა ორობითი. მასში გამოყენებულია GetString, ამიტომ მას სჭირდება წასვლა მეტი cs50.o, და linker smooshes მათ ერთად და აკოპირებს GetString შევიდა ამ ფაილის და გამოდის შესრულებადი რომ ყველა ფუნქციით სჭირდება. ამიტომ cs50.o არ არის რეალურად O ფაილი, მაგრამ მჭიდრო საკმარისი, რომ არ არსებობს ფუნდამენტური განსხვავება. ასე აკავშირებს მხოლოდ მოაქვს bunch of ფაილი ერთად რომ ცალკე შეიცავდეს ყველა ფუნქციებს მე უნდა გამოვიყენოთ და ქმნის შესრულებად, რომელიც რეალურად აწარმოებს. და ისე, რომ ასევე რასაც ვამბობდით ადრე სადაც შეგიძლიათ აქვს 1000. გ ფაილი თქვენ კომპილაციის მათ ყველა. o ფაილი რომელიც სავარაუდოდ ხოლო, მაშინ შეცვლის 1. გ ფაილი. თქვენ მხოლოდ უნდა recompile რომ 1. გ ფაილი და შემდეგ relink ყველაფერი, დაუკავშირონ ყველაფერი უკან ერთად. [სტუდენტი] როდესაც ჩვენ აკავშირებს ჩვენ წერენ lcs50? Yeah, ეგრეთ lcs50. რომ დროშა სიგნალებს linker რომ თქვენ უნდა აკავშირებს ამ ბიბლიოთეკაში. კითხვები? გვაქვს წავიდა მეტი ორობითი გარდა, რომ 5 წამში პირველ ლექციას? მე ასე არ ვფიქრობ. თქვენ უნდა იცოდეს, ყველა დიდი Os რომ ჩვენ წავიდა მეტი, და თქვენ უნდა შეეძლოს, თუ მივეცით თქვენ ფუნქცია, თქვენ უნდა შეეძლოს იმის თქმა, რომ ეს დიდი O, უხეშად. ან კარგად, დიდი O არის უხეში. ასე რომ, თუ ხედავთ წყობილი ამისთვის მარყუჟების looping იმავე რაოდენობის ნივთები, მოსწონს int i, მე > [სტუდენტი] N კვადრატში. >> ეს tends უნდა იყოს N კვადრატში. თუ თქვენ არ სამმაგი წყობილი, ეს tends უნდა იყოს N cubed. ასე რომ ერთგვარი რაც თქვენ უნდა შეეძლოს აღვნიშნო, დაუყოვნებლივ. თქვენ უნდა იცოდეთ Insertion დალაგება და ბუშტი დალაგება და შერწყმის დალაგება და ყველა იმ. უფრო ადვილია მესმის, რატომ არიან ისინი იმ N კვადრატში და N შესვლა N და ყველა რომ რადგან ვფიქრობ, იქ იყო ვიქტორინა ერთი წლის სადაც ჩვენ ძირითადად მისცა თქვენ განხორციელების bubble sort და თქვა: "რა არის ქრონომეტრაჟი ამ ფუნქციას?" ასე რომ, თუ თქვენ აღიარებს მას, როგორც ბუშტი დალაგების, მაშინ დაუყოვნებლივ ამბობენ N კვადრატში. მაგრამ თუ უბრალოდ შეხედეთ მას, თქვენ კი არ უნდა გააცნობიეროს მისი ბუშტი დალაგება; შეგიძლიათ უბრალოდ ვიტყვი, რომ ეს ამით და ამ. ეს არის n კვადრატში. [სტუდენტი] არსებობს რაიმე მკაცრი მაგალითები შეგიძლიათ ამუშავება, მოსწონს მსგავსი იდეა მჭიდროდაა გარეთ? მე არ ვფიქრობ, რომ ჩვენ მოგცემთ ნებისმიერი მკაცრი მაგალითები. Bubble sort რამ არის, როგორც მკაცრი, როგორც ჩვენ წავიდოდა, და კიდევ, რომ, როგორც თქვენ გვესმის, რომ თქვენ iterating მეტი მასივი თითოეული ელემენტი მასივი, რომელიც იქნება რაღაც რომ n კვადრატში. არსებობს ზოგადი კითხვები, როგორიცაა უფლება აქ გვაქვს - Oh. უბრალოდ მეორე დღეს, დაგ მტკიცებით, "მე არ გამოიგონა ალგორითმი რომ შეგიძლიათ დაალაგოთ მასივი "საქართველოს N ნომრები O (შესვლა N) დროს!" მაშ როგორ ვიცით, რომ შეუძლებელია? [Inaudible სტუდენტი საპასუხოდ] >> Yeah. სულ ცოტა, თქვენ უნდა შეეხოთ თითოეულ ელემენტს მასივი, ამიტომ შეუძლებელია დასალაგებლად მასივი - თუ ყველაფერი არასორტირებული მიზნით, მაშინ თქვენ უნდა ეხება ყველაფერს მასივი, ამიტომ შეუძლებელია ამის გაკეთება ნაკლებ O of n. [სტუდენტი] თქვენ დაგვანახა, რომ მაგალითად, რომ ვერ გააკეთებს ამას O of n თუ თქვენ იყენებთ მეხსიერების დიდ ნაწილს. >> Yeah. და that's - მე დაგვავიწყდეს, თუ რა that's - ეს არის ის დათვლის დალაგება? Hmm. სწორედ რიცხვი დახარისხება ალგორითმი. მე ეძებდა სპეციალური სახელი ამ რომ მე ვერ გაიხსენა გასულ კვირას. Yeah. ეს არის სახის ჯიშები, რომელსაც შეუძლია სრულფასოვნად რამ დიდი O of n. მაგრამ არსებობს შეზღუდვები, როგორიც შეგიძლიათ მხოლოდ მთელი რიცხვები მდე გარკვეული რაოდენობა. Plus თუ თქვენ ცდილობს დასალაგებლად რაღაც that's - თუ თქვენი მასივი 012, -12, 151, 4 მილიონი, მაშინ ეს ერთჯერადი ელემენტს აპირებს მთლიანად ჩაშლის მთელი დახარისხება. კითხვები? [სტუდენტი] თუ თქვენ გაქვთ რეკურსიული ფუნქცია და უბრალოდ იღებს რეკურსიული მოუწოდებს ფარგლებში დაბრუნების განაცხადი, რომ კუდი რეკურსიული, და ასე იქნება, რომ არ გამოიყენოთ მეტი მეხსიერების დროს Runtime ან იქნებოდა მინიმუმ გამოიყენოთ შესადარებელი მეხსიერების როგორც iterative გამოსავალი? [Bowden] დიახ. იგი სავარაუდოდ ერთგვარად ნელა, მაგრამ ნამდვილად არ. კუდი რეკურსიული არის საკმაოდ კარგი. ვეძებთ კვლავ დასტის ფარგლებში, ვთქვათ გვაქვს მთავარი და ჩვენ გვაქვს int ბარი (int x) ან რამე. ეს არ არის სრულყოფილი რეკურსიული ფუნქცია, მაგრამ დაბრუნების ბარი (x - 1). ამიტომ ცხადია, რომ ეს არის სრულყოფილი. თქვენ უნდა ბაზის შემთხვევებში და პერსონალი. მაგრამ იდეა აქ მდგომარეობს იმაში, რომ ეს კუდი რეკურსიული, რაც იმას ნიშნავს, როდესაც მთავარ მოუწოდებს ბარი იგი აპირებს მიიღოს მისი დასტის ჩარჩო. ამ დასტის ჩარჩო იქ იქნება პატარა ბლოკი მეხსიერება რაც შეესაბამება მისი არგუმენტი x. და ასე ვთქვათ ძირითადი ხდება მოვუწოდო ბარი (100); ამიტომ x იწყებს, როგორც 100. თუ შემდგენელი აღიარებს, რომ ეს არის კუდი რეკურსიული ფუნქცია, მაშინ, როდესაც ბარი იცავს თავის რეკურსიული ზარი ბარი, ნაცვლად მიღების ახალი დასტის ფორმატი, რომელიც არის სადაც დასტის იწყებს მზარდი დიდწილად, საბოლოოდ იგი გადაეყარონ ბევრი და შემდეგ თქვენ მიიღებთ segfaults რადგან მეხსიერების იწყება colliding. ასე რომ ნაცვლად მიღების საკუთარი დასტის ჩარჩოში, მას შეუძლია გააცნობიეროს, Hey, მე არასოდეს რეალურად უნდა დაუბრუნდეს ამ დასტის ჩარჩო, ასე ნაცვლად მე უბრალოდ შეცვალეთ ეს არგუმენტი ერთად 99 და შემდეგ დაიწყოს ბარი მთელი. და მერე ამას კვლავ და მიაღწევს დაბრუნების ბარი (x - 1), და ნაცვლად მიღების ახალი დასტის ჩარჩოს, იგი მხოლოდ შეცვლის მისი ამჟამინდელი არგუმენტი ერთად 98 და მაშინ ხტომა თავში დასაბამიდანვე ბარი. იმ ოპერაციებს, შეცვლის, რომ 1 ღირებულება დასტის და jumping დასაწყისში, საკმაოდ ეფექტური. ასე არა მხოლოდ არის ამ იგივე მეხსიერების გამოყენებას, როგორც ცალკეული ფუნქცია რომელიც iterative იმიტომ, რომ თქვენ მხოლოდ გამოყენებით 1 დასტის ჩარჩო, მაგრამ თქვენ არ განიცდიდა downsides , რომელმაც უნდა მოვუწოდებთ ფუნქციები. დარეკვის ფუნქციები შეიძლება იყოს გარკვეულწილად ძვირი, რადგან მას ყველაფერი ამ კონფიგურაციის და teardown და ყველა ამ პერსონალის. ასე რომ, ეს კუდი უკან არის კარგი. [სტუდენტი] რატომ არ შევქმნათ ახალი ნაბიჯები? რადგან ეს აცნობიერებს ამას არ სჭირდება. ზარი ბარი მხოლოდ დაბრუნების რეკურსიული ზარი. ასე რომ, ეს არ უნდა გავაკეთოთ არაფერი დაბრუნებული მნიშვნელობა. უბრალოდ აპირებს დაუყოვნებლივ დაბრუნება. ამიტომ უბრალოდ აპირებს შეცვალოს საკუთარი არგუმენტი და დაიწყონ ზე. და ასევე, თუ თქვენ არ კუდი რეკურსიული ვერსია, მაშინ თქვენ გაქვთ ყველა ამ ბარები, სადაც როცა ეს ბარი ბრუნდება ეს უნდა დაიბრუნოს ღირებულება ამ ერთი, მაშინ ეს ბარი დაუყოვნებლივ დააბრუნებს და ის დააბრუნებს მისი ღირებულება ამ ერთი, მაშინ ის უბრალოდ აპირებს დაუყოვნებლივ დაბრუნდეს და დაიბრუნოს ღირებულება ამ ერთ. ასე რომ თქვენ გადარჩენის ამ popping ყველა ამ საკითხზე გამორთვა დასტის მას შემდეგ, რაც დაბრუნების ღირებულება მხოლოდ აპირებს გადაეცემა ყველა გზა უკან მდე მაინც. რატომ არა მხოლოდ ჩაანაცვლოს ჩვენი არგუმენტი მიაწოდა უახლესი არგუმენტი და დაიწყონ ზე? თუ ფუნქცია არ არის კუდი რეკურსიული, თუ რაღაც მსგავსი - [სტუდენტი] თუ ბარი (x + 1). >> Yeah. ასე რომ, თუ თქვენ დააყენოს ის მდგომარეობა, მაშინ თქვენ აკეთებთ რაღაც ერთად დაბრუნებული მნიშვნელობა. ან თუნდაც, თუ თქვენ უბრალოდ დაბრუნების 2 * ბარი (x - 1). ახლა ბარი (x - 1) სჭირდება დაბრუნებას, რათა ეს გამოთვლა 2 ჯერ რომ ღირებულება, ახლა ეს იმას სჭირდება საკუთარი ცალკე დასტის ჩარჩო, და ახლა, რაც არ უნდა მძიმე თქვენ ცდილობენ, თქვენ აპირებს უნდა - ეს არ არის კუდი რეკურსიული. [სტუდენტი] უნდა ვეცადოთ, რათა უკან დაბრუნების მიზანია ამისთვის კუდი უკან - [Bowden] In იდეალური მსოფლიოში, მაგრამ CS50 თქვენ არ. მისაღებად კუდი უკან, ძირითადად, შეიქმნას დამატებითი არგუმენტი სადაც ბარი მიიღებს int x შევიდა Y და Y შეესაბამება საბოლოო რამ გსურთ დაბრუნებას. ასე რომ მაშინ ეს თქვენ უნდა დაბრუნების ბარი (x - 1), 2 * Y. ასე რომ უბრალოდ მაღალი დონის, თუ როგორ გარდაქმნის რამ იქნება კუდი რეკურსიული. მაგრამ ზედმეტი არგუმენტი - ხოლო შემდეგ დასრულდება, როდესაც თქვენ მიღწევა თქვენი ბაზა შემთხვევაში, უბრალოდ დაბრუნების Y რადგან თქვენ უკვე დაგროვების მთელი დროის დაბრუნებული მნიშვნელობა რომ გსურთ. თქვენ სახის უკვე აკეთებს ამას iteratively მაგრამ მისი გამოყენება რეკურსიული მოუწოდებს. კითხვები? [სტუდენტი] იქნებ შესახებ კურსორი არითმეტიკა, ასე, როდესაც გამოყენებით სტრიქონები. >> დარწმუნებული. Pointer არითმეტიკული. გამოყენებისას სიმები ადვილი რადგან სიმები არიან char ვარსკვლავი, chars არიან სამუდამოდ და ყოველთვის ერთი ბაიტი, და ა.შ. კურსორის არითმეტიკული უდრის რეგულარული არითმეტიკული როცა თქვენ საქმე სტრიქონები. მოდით უბრალოდ, ვამბობთ char * s = "Hello". ამიტომ ბლოკი მეხსიერება. ნიშანდობლივია 6 bytes რადგან თქვენ ყოველთვის გვჭირდება null terminator. და char * s აპირებს აღვნიშნო, რომ დასაწყისში მასივი. რათა მიუთითებს იქ. ახლა, ეს არის ძირითადად, თუ როგორ ნებისმიერი მასივი მუშაობს, მიუხედავად იმისა, რომ ეს იყო დაბრუნებას malloc თუ ის შესახებ Stack. ნებისმიერი მასივი ძირითადად მომცეთ დაწყების მასივი, და მაშინ ნებისმიერი ოპერაციის მასივი, ნებისმიერი ინდექსირებას, მხოლოდ მიდის, რომ მასივი გარკვეული წანაცვლება. ამიტომ როდესაც ვამბობ, რომ მსგავსი რამ s [3]; ამ აპირებს და დათვლის 3 chars სისტემაში ასე s [3], ჩვენ გვაქვს 0, 1, 2, 3, ასე s [3] აპირებს მიმართოს ამ ლ. [სტუდენტი] და ჩვენ შეგვიძლია მივაღწიოთ იმავე ღირებულების ამით s + 3 და შემდეგ ფრჩხილებში ვარსკვლავი? დიახ. ეს არის ექვივალენტური * (s + 3); და ეს სამუდამოდ და ყოველთვის ექვივალენტი არ აქვს მნიშვნელობა, თუ რას აკეთებთ. თქვენ არასოდეს უნდა გამოვიყენოთ bracket სინტაქსი. თქვენ ყოველთვის შეგიძლიათ გამოიყენოთ * (s + 3) სინტაქსი. ხალხი ტენდენცია მინდა bracket სინტაქსი, თუმცა. [სტუდენტი] ასე ყველა კოლექტორები რეალურად მხოლოდ პოინტერები. არსებობს უმნიშვნელო განსხვავება როდესაც ვამბობ, რომ int x [4]; >> [სტუდენტი] აქვს თუ არა, რომ შევქმნათ მეხსიერება? [Bowden], რომ აპირებს შექმნას 4 ints on დასტის, ასე 16 ბაიტი საერთო. ის აპირებს შექმნას 16 ბაიტი on Stack. x არ ინახება არსად. უბრალოდ სიმბოლო გულისხმობდა დაწყების რამ. იმიტომ, რომ თქვენ განაცხადა მასივი შიგნით ამ ფუნქციას, რა შემდგენელი აპირებს მხოლოდ ჩაანაცვლოს ყველა ინსტანციის ცვლადი x ერთად სადაც ეს მოხდა, აირჩიოს, რომ ეს 16 ბაიტი. მას არ შეუძლია გააკეთოს, რომ char * s რადგან s არის ფაქტობრივი მაჩვენებელი. იგი თავისუფალია მაშინ აღვნიშნო, რომ სხვა რამ. x არის მუდმივი. შეგიძლიათ არ აქვს ის წერტილი სხვადასხვა მასივი. >> [სტუდენტი] Okay. მაგრამ ამ იდეას, ამ ინდექსირებას, იგივეა მიუხედავად იმისა, რომ ეს ტრადიციული მასივი ან თუ ეს მაჩვენებელი რაიმე ან თუ მომცეთ malloced მასივი. და რეალურად, ეს ასე ექვივალენტს, რომ ასევე იგივე. ეს ფაქტიურად მხოლოდ ითარგმნება რა შიგნით ფრჩხილებში და რაც დარჩა ფრჩხილები, დასძენს მათი ერთად, და dereferences. ასე რომ, ეს უბრალოდ, როგორც მოქმედი, როგორც * (s + 3) ან s [3]. [სტუდენტი] შეგიძლიათ აქვს პოინტერები მიუთითებს 2 განზომილებიანი მასივები? ეს უფრო რთული. ტრადიციულად, არ. 2 განზომილებიანი მასივი მხოლოდ 1 განზომილებიანი მასივი რამდენიმე მოსახერხებელი სინტაქსი რადგან როდესაც ვამბობ, რომ int x [3] [3], ეს მართლაც მხოლოდ 1 მასივში 9 ღირებულებებს. და ა.შ. როცა ინდექსი, შემდგენელი იცის რას ვგულისხმობ. თუ მე ვიტყვი, x [1] [2], იგი დარწმუნებულია, მინდა წასვლა მეორე რიგის, ამიტომ აპირებს გამოტოვოთ პირველი 3, და შემდეგ მას სურს მეორე რამ, რომ, ამიტომ აპირებს ამ ერთ. მაგრამ ეს ჯერ კიდევ მხოლოდ ერთი განზომილებიანი მასივი. და თუ მინდოდა დაავალოს მომცეთ, რომ მასივი, მე ვიტყოდი, int * p = x; გაცნობის x უბრალოდ - ეს უხეში ამბობდა გაცნობის x რადგან ეს მხოლოდ სიმბოლოა და ეს არ ფაქტობრივი ცვლადი, მაგრამ ეს მხოლოდ int *. x არის მხოლოდ მომცეთ დაწყება ამ. >> [სტუდენტი] Okay. და მე ვერ შეძლებს წვდომისათვის [1] [2]. ვფიქრობ, რომ არსებობს სპეციალური სინტაქსი გამოცხადების მაჩვენებელი, რაღაც სასაცილოა მოსწონს int (* P [- რაღაც აბსოლუტურად სასაცილოა. ისიც კი არ იციან. მაგრამ არის სინტაქსი გამოცხადების პოინტერები მოსწონს ერთად ფრჩხილებში და რამ. ეს შეიძლება არც კი მოგცემთ, რომ. მე ვერ ვიხსენებთ რაღაც რომ მითხრათ სიმართლე. მე ვეძებოთ იგი მოგვიანებით, თუ არსებობს სინტაქსი წერტილი. მაგრამ თქვენ არასოდეს ჩანს. და მაშინაც კი, სინტაქსის იმდენად არქაული, რომ თუ თქვენ გამოიყენოს იგი, ხალხი იქნება baffled. მრავალგანზომილებიანი მასივები საკმაოდ იშვიათი არ არის. თქვენ საკმაოდ ბევრი - ისე, თუ თქვენ აკეთებთ matrix რამ ეს არ იქნება იშვიათი, მაგრამ C თქვენ იშვიათად იქნება გამოყენებით მრავალგანზომილებიანი მასივები. Yeah. >> [სტუდენტი] ვთქვათ თქვენ გაქვთ მართლაც ხანგრძლივი მასივი. ასე რომ ვირტუალური მეხსიერების იქნებოდა, როგორც ჩანს, ყველა ზედიზედ, მოსწონს ელემენტების უფლება მომდევნო ერთმანეთს, მაგრამ ფიზიკური მეხსიერება, რომ შესაძლებელი რომ რომ გაიყოფა up? >> დიახ. როგორ ვირტუალური მეხსიერება სამუშაოების უბრალოდ ჰყოფს - ერთეულის გამოყოფის არის გვერდი, რომელიც tends უნდა იყოს 4 kilobytes, და ამრიგად, როდესაც პროცესში ამბობს, hey, მინდა გამოვიყენო ეს მეხსიერება, ოპერაციული სისტემა აპირებს გამოყოს ის 4 kilobytes რომ პატარა ბლოკი მეხსიერება. მაშინაც კი, თუ თქვენ მხოლოდ ერთი პატარა byte მთელ ბლოკი მეხსიერება, ოპერაციული სისტემა აპირებს მისცეს მას სრული 4 kilobytes. მერე რა ეს ნიშნავს, მე შეიძლება - ვთქვათ ეს არის ჩემი Stack. ეს დასტის შეიძლება გამოყოფილი. ჩემი დასტის შეიძლება მეგაბაიტები და მეგაბაიტები. ჩემი დასტის შეიძლება იყოს უზარმაზარი. მაგრამ დასტის თავად უნდა გაიყო ინდივიდუალური გვერდებზე, რომელიც, თუ დავაკვირდებით აქ ვთქვათ ეს არის ჩვენი RAM, თუ მაქვს 2 გბ ოპერატიული მეხსიერება, ეს არის ფაქტობრივი მისამართი 0 მოსწონს zeroth byte ჩემი RAM, და ეს არის 2 გიგაბაიტი ყველა გზა ქვემოთ აქ. ასე რომ, ეს გვერდი შესაძლოა შეესაბამება ამ ბლოკის მეტი აქ. ეს გვერდი შესაძლოა შეესაბამება ამ ბლოკის მეტი აქ. ეს შეიძლება შეესაბამება ამ ერთი მეტი აქ. ამიტომ ოპერაციული სისტემის უფასო დაავალოს ფიზიკური მეხსიერება ნებისმიერი ინდივიდუალური გვერდზე თვითნებურად. და ეს ნიშნავს, რომ თუ ამ საზღვრის ხდება straddle მასივი, array ხდება უნდა დაუტოვებიათ ამ და უფლება ამ ბრძანებით გვერდზე, მაშინ ეს მასივი იქნება გაყოფილი, ფიზიკური მეხსიერება. და მაშინ, როდესაც თავი დაანებონ პროგრამა, როდესაც პროცესი დამთავრდა, ამ mappings კიდევ წაშლილია და შემდეგ ეს უფასო გამოიყენოს ამ პატარა ბლოკები სხვა რამ. სხვა კითხვები? [სტუდენტი] მაჩვენებელი არითმეტიკული. >> Oh Yeah. სიმები იყო ადვილი, მაგრამ ეძებს რაღაც ints, ასე დაბრუნდა int x [4]; თუ არა ეს არის array თუ ის მომცეთ malloced მასივი 4 რიცხვებით, ეს იქნება დამუშავებული იგივე გზით. [სტუდენტი] ასე კოლექტორები არიან ბევრი? [Bowden] მასივები არ არიან ბევრი. >> [სტუდენტი] Oh. [Bowden] ამ ტიპის მასივი tends იყოს დასტის თუ თქვენ გამოაცხადა at - იგნორირება გლობალური ცვლადები. არ გამოიყენოთ გლობალური ცვლადები. შიგნით ფუნქციის ვამბობ int x [4]; ის აპირებს შექმნას 4-მთელი რიცხვი ბლოკი დასტის ამ მასივი. მაგრამ ეს malloc (4 * sizeof (int)); აპირებს გაგრძელდება ბევრი. მაგრამ მას შემდეგ, რაც ამ ეტაპზე მე შემიძლია გამოვიყენო X და P ში საკმაოდ ბევრი იგივე გზები, გარდა გამონაკლისი ვთქვი შესახებ შეგიძლიათ reassign გვ. ტექნიკურად, მათი ზომის არიან განსხვავებული, მაგრამ ეს სრულიად შეუსაბამო. თქვენ არასოდეს რეალურად გამოიყენონ თავიანთი ზომის. P მე შეიძლება ითქვას, P [3] = 2; x ან [3] = 2; თქვენ შეგიძლიათ გამოიყენოთ ისინი ზუსტად იგივე გზა არსებობს. ამიტომ კურსორი არითმეტიკული არის - დიახ. [სტუდენტი] მიგაჩნიათ თუ არა არ უნდა გავაკეთოთ P * თუ თქვენ გაქვთ ფრჩხილები? ფრჩხილებში არიან დაფარული dereference. >> Okay. სინამდვილეში, ასევე თუ რას ამბობდა ერთად შეგიძლიათ მიიღოთ მრავალგანზომილებიანი მასივები ერთად პოინტერები, თუ რა შეგიძლიათ გააკეთოთ მსგავსი რამ, ასე ვთქვათ, int ** PP = malloc (sizeof (int *) * 5); მე უბრალოდ დავწერ აქ ყველა პირველ. მე არ მინდოდა, რომ ერთი. Okay. რა გავაკეთე აქ არის - ეს უნდა იყოს PP [i]. ამიტომ PP არის მომცეთ მაჩვენებელი. თქვენ mallocing PP აღვნიშნო, რომ მასივი 5 int ვარსკვლავს. ასე რომ მეხსიერება გაქვთ on დასტის გვ იგი აპირებს აღვნიშნო, რომ მასივი 5 ბლოკები რომლებიც ყველა თავად პოინტერები. და მაშინ როდესაც მე malloc ქვემოთ აქ, მე malloc რომ თითოეული იმ მცირე პოინტერები უნდა აღვნიშნო, რომ ცალკე ბლოკი 4 ბაიტი on ბევრი. ასე რომ, ეს მიუთითებს 4 ბაიტი. და ეს ერთი ქულა სხვადასხვა 4 ბაიტი. და ყველა მათგანი აღვნიშნო, რომ საკუთარი 4 ბაიტი. ეს მაძლევს გზას აკეთებს მრავალგანზომილებიანი რამ. მე შეიძლება ითქვას, PP [3] [4], მაგრამ ახლა ეს არ არის იგივე როგორც მრავალგანზომილებიანი მასივები რადგან მრავალგანზომილებიანი მასივები ეს ნათარგმნი [3] [4] ერთ ოფსეტური შევიდა x მასივი. ეს dereferences P, ხელმისაწვდომი მესამე ინდექსი, შემდეგ dereferences რომ და ხელმისაწვდომი - 4 იქნებოდა არასწორი - მეორე ინდექსი. ვინაიდან, როდესაც ჩვენ გვქონდა int x [3] [4] ადრე როგორც მრავალგანზომილებიანი მასივი და როდესაც თქვენ გაორმაგება bracket ეს მართლაც მხოლოდ ერთი dereference, თქვენ შემდეგ ერთი მაჩვენებელი და შემდეგ წანაცვლება, ეს მართლაც 2D დამოწმება. თქვენ დაიცვას 2 ცალკე პოინტერები. ასე რომ, ეს ასევე ტექნიკურად საშუალებას გაძლევთ მრავალგანზომილებიანი მასივები სადაც თითოეულ ინდივიდუალური მასივი სხვადასხვა ზომის. ამიტომ ვფიქრობ Jagged მრავალგანზომილებიანი მასივები არის რასაც ის მოუწოდა რადგან მართლაც პირველი, რაც შეიძლება აღვნიშნო, რომ ის, რაც აქვს 10 ელემენტები, მეორე რამ შეიძლება აღვნიშნო, რომ ის, რაც აერთიანებს 100 ელემენტებს. [სტუდენტი] არსებობს თუ არა ლიმიტი რაოდენობის პოინტერები თქვენ შეგიძლიათ მიუთითებს სხვა პოინტერები? >> პოსტები თქვენ შეგიძლიათ int ***** გვ. თავში მაჩვენებელი არითმეტიკა - >> [სტუდენტი] Oh. >> Yeah. [სტუდენტი] თუ მაქვს int *** P და მერე გავაკეთო dereferencing და ვამბობ P * უდრის ამ მნიშვნელობის, იგი მხოლოდ აპირებს 1 დონე dereferencing? >> დიახ. ასე რომ, თუ მინდა წვდომისათვის, რაც ბოლო მაჩვენებელი არის მიუთითებს - მერე შენ *** გვ. >> Okay. ასე რომ, ეს არის P ქულა 1 კვარტალი, რაოდენობა მეორეში ბლოკი, რაოდენობა სხვა ბლოკი. მაშინ თუ * p = რაღაც, მაშინ იცვლება ამ აქამდე აღვნიშნო, რომ სხვადასხვა ბლოკში. >> Okay. [Bowden] და თუ ეს იყო malloced, მაშინ არ არის გაჟონა მეხსიერება თუ თქვენ მოხდეს განსხვავებული მითითება ამ რადგან ვერ დაიბრუნებს იმ განსხვავებით, რომ თქვენ მხოლოდ დაუშინეს დაშორებით. Pointer არითმეტიკული. int x [4]; აპირებს გამოყოს მასივი 4 რიცხვებით სადაც x აპირებს აღვნიშნო, რომ დასაწყისში მასივი. ამიტომ როდესაც ვამბობ, რომ მსგავსი რამ x [1]; მინდა ეს ნიშნავს წასვლა მეორე რიცხვი მასივში, რაც იქნება ეს ერთი. მაგრამ რეალურად, რომ 4 ბაიტი შევიდა მასივი რადგან ეს რიცხვი იკავებს 4 ბაიტს. ამიტომ ოფსეტური of 1 ნამდვილად ნიშნავს ურთიერთჩათვლის of 1 ჯერ ზომა ნებისმიერი ტიპის მასივი. ეს არის მასივი რიცხვებით, ასე რომ იცის გავაკეთოთ 1 ჯერ ზომა int როდესაც მას სურს წანაცვლება. სხვა სინტაქსი. გახსოვდეთ, რომ ეს არის ექვივალენტური * (x + 1); როდესაც ვამბობ კურსორი + 1, რა, რომ ანაზღაურება არის მისამართი, რომ მომცეთ არის შენახვის პლუს 1 ჯერ ზომა ტიპის მაჩვენებელი. ასე რომ, თუ x = ox100, მაშინ x + 1 = ox104. და შეგიძლიათ ბოროტად გამოიყენოს ეს და ვთქვათ რაღაც char * გ = (char *) x; და ახლა გ იქნება ერთსა და იმავე მისამართზე, როგორც x. გ იქნება ტოლი ox100, მაგრამ გ + 1 იქნება ტოლი ox101 რადგან კურსორი არითმეტიკული დამოკიდებულია ტიპის მაჩვენებელი, რომ თქვენ შეავსოთ. ასე რომ გ + 1, ის უყურებს გ, ეს char მაჩვენებელი, ამიტომ აპირებს დაამატოთ 1 ჯერ ზომა char, რომელიც ყოველთვის იქნება 1, ასე რომ თქვენ მიიღოთ 101, ხოლო თუ x, რომელიც არის ასევე დღემდე 100, x + 1 იქნება 104. [სტუდენტი] შეგიძლიათ გამოიყენოთ C + + დახვეწის მიზნით თქვენი კურსორი მიერ 1? დიახ, შეგიძლიათ. თქვენ ვერ, რომ x რადგან x არის მხოლოდ სიმბოლო, ეს არის მუდმივი, თქვენ ვერ შეცვლის x. მაგრამ გ ხდება მხოლოდ კურსორი, ისე C + + სრულიად სწორი და ის ნამატი მიერ 1. თუ C იყო int *, მაშინ C + + იქნებოდა 104. + + არ მომცეთ არითმეტიკული ისევე როგორც C + 1 ექნება გაკეთდეს მაჩვენებელი არითმეტიკული. ეს არის რეალურად რამდენად ბევრი რამ, როგორიცაა შერწყმა დალაგება - იმის ნაცვლად, რომ შექმნას ასლები რამ, შეგიძლიათ ნაცვლად გაივლის - Like თუ მინდოდა გაივლის ამ ნახევარში მასივი - მოდით წაშლას ზოგიერთი ამ. ვთქვათ მინდოდა გაივლის ამ მხარეს მასივი შევიდა ფუნქცია. რა მე გადავიდეთ რომ ფუნქცია? თუ მე გაივლის x, მე გავლით ამ მისამართზე. მაგრამ მინდა გაივლის ამ კონკრეტულ მისამართზე. ასე რა უნდა გაიაროს? [სტუდენტი] Pointer + 2? [Bowden] So x + 2. დიახ. რომ იქნება ამ მისამართზე. თქვენ ასევე ძალიან ხშირად ვხედავ მას, როგორც x [2] და შემდეგ მისამართს რომ. ასე, რომ თქვენ უნდა მიიღოს მისამართი რადგან bracket არის დაფარული dereference. x [2] ეხება ღირებულება, რომელიც არის ამ ყუთში, შემდეგ კი გსურთ მისამართი რომ ყუთი, ასე რომ თქვენ ამბობენ & x [2]. ასე რომ, თუ როგორ რაღაც შერწყმა დალაგების სადაც გსურთ გაიაროს ნახევარ სიაში რაიმე ნამდვილად უბრალოდ გაივლის და X [2] და ახლა რამდენადაც რეკურსიული ზარის ეხება, ჩემი ახალი მასივი იწყება იქ. ბოლო წუთი კითხვები. [სტუდენტი] თუ ჩვენ არ დააყენა ampersand ან - რა რომ ქვია? >> Star? [სტუდენტი] Star. >> ტექნიკურად, dereference ოპერატორი, მაგრამ - >> [სტუდენტი] Dereference. თუ ჩვენ არ დააყენა ვარსკვლავი ან ampersand, რა მოხდება თუ მე უბრალოდ ამბობენ Y = X და X-ის მაჩვენებელი? რა არის გაცნობის Y? >> [სტუდენტი] მე უბრალოდ, ვამბობთ ეს მაჩვენებელი 2. ასე რომ, თუ თქვენ უბრალოდ ამბობენ Y = x, ახლა x და y წერტილი იგივე. >> [სტუდენტი] ქულა, რათა იგივე. და თუ x არის int მაჩვენებელი? >> იქნებოდა უჩივიან, რადგან ვერ დაავალოს პოინტერები. [სტუდენტი] Okay. გახსოვდეთ, რომ გჭირდებათ, მიუხედავად იმისა, რომ ჩვენ დავხატოთ მათ ისრები, მართლაც ყველა მათ მაღაზიაში - int * x - მართლაც ყველა X-ის შენახვის არის რაღაც ox100, რაც ჩვენ არ უნდა წარმოადგენდეს, როგორც მიუთითებს ბლოკი ინახება 100. ამიტომ როდესაც ვამბობ, რომ int * y = x; მე უბრალოდ კოპირება ox100 შევიდა Y, რაც ჩვენ უბრალოდ აპირებს წარმოადგინოს როგორც Y, ასევე მიუთითებს ox100. და თუ ვიტყვი int i = (int) x, მერე აპირებს შესანახად რასაც ღირებულება ox100 არის შიგნით, მაგრამ ახლა ეს იქნება გაგებული, როგორც მთელი რიცხვი ნაცვლად მაჩვენებელი. მაგრამ არ არის საჭირო მსახიობი ანდა იქნება უჩივიან. [სტუდენტი] ასე რომ თქვენ საშუალება მისცეს - ხომ უნდა ისროდნენ int of x ან ჩამოსხმის int of Y? [Bowden] რა? [სტუდენტი] Okay. ამის შემდეგ ფრჩხილებში არის იქ იქნება x ან ay იქ? [Bowden] ან. x და y არიან ექვივალენტი. >> [სტუდენტი] Okay. რადგან ისინი ორივე პოინტერები. >> Yeah. [სტუდენტი] ასე რომ ის შესანახად თექვსმეტობითი 100 წელს მთელი ფორმით? >> [Bowden] Yeah. მაგრამ არ ღირებულება რაც არ მიუთითებს. [Bowden] Yeah. >> [სტუდენტი] ასე რომ მხოლოდ მისამართი რიცხვი ფორმით. Okay. [Bowden] თუ უნდოდა რაღაც უცნაური მიზეზი, თქვენ შეიძლება მხოლოდ გაუმკლავდეთ პოინტერები და არასდროს გაუმკლავდეთ რიცხვებით და უბრალოდ იყოს int * x = 0. მაშინ თქვენ აპირებს მისაღებად ნამდვილად დაბნეული ერთხელ მაჩვენებელი არითმეტიკული იწყება ხდება. ასე რომ ციფრები, რომ მათ შესანახად არის უაზრო. უბრალოდ, თუ როგორ დასრულდება მდე წერით მათ. ასე რომ, მე ვარ თავისუფალი კოპირება ox100 საწყისი int * to int, და მე თავისუფალი დაავალოს - you're ალბათ აპირებს მისაღებად yelled დროს არ აძლევენ - მე უფასო დაავალოს რაღაც (int *) ox1234 ამ თვითნებური int *. ამიტომ ox123 ისეთივე მოქმედებს მეხსიერების მისამართი როგორც არის & Y. & Y ხდება დაბრუნდეს რაღაც რომ არის საკმაოდ ბევრი ox123. [სტუდენტი] რა, რომ იყოს მართლა მაგარი გზა გადასვლა თექვსმეტობითი to ათობითი ფორმა, მინდა თუ გაქვთ მომცეთ და მიიღო ის როგორც int? [Bowden] შეგიძლიათ ნამდვილად უბრალოდ ბეჭდვა გამოყენებით, როგორიცაა printf. ვთქვათ მაქვს int y = 100. ამიტომ printf (% d \ n - როგორც თქვენ უნდა უკვე ვიცით - ბეჭდვა, რომ როგორც მთელი რიცხვი,% x. ჩვენ მხოლოდ ბეჭდვა, როგორც თექვსმეტობითი. ასე რომ კურსორი არ ინახება როგორც თექვსმეტობითი, და რიცხვი არ არის ინახება როგორც ათობითი. ყველაფერი ინახება როგორც ორობითი. უბრალოდ, ჩვენ გვსურს წავახალისოთ ნახოთ პოინტერები როგორც თექვსმეტობითი რადგან მიგვაჩნია, რომ რამ ამ 4-byte ბლოკები, და მეხსიერების მისამართები ტენდენცია იყოს ნაცნობი. ჩვენ მსგავსად, თუ იგი იწყება BF, მაშინ ეს ხდება იქნება Stack. ასე რომ ეს მხოლოდ ჩვენი ინტერპრეტაცია პოინტერები როგორც თექვსმეტობითი. Okay. ნებისმიერი ბოლო კითხვები? მე აქ ცოტა შემდეგ თუ არაფერი. და ეს ბოლომდე რომ. [სტუდენტი] YAY! [ტაში] [CS50.TV]