[Powered by Google Translate] [Seksyen 4 - Lebih Selesa]
[Rob Bowden - Universiti Harvard]
[Ini adalah CS50. - CS50.TV]
Kami mempunyai esok kuiz, dalam kes anda semua tidak tahu bahawa.
Ia pada asasnya atas segala-galanya yang anda boleh dilihat di dalam kelas atau sepatutnya dilihat di dalam kelas.
Ini termasuk petunjuk, walaupun mereka satu topik yang sangat baru-baru ini.
Anda sekurang-kurangnya harus memahami tahap tinggi mereka.
Apa-apa yang telah hilang di dalam kelas anda perlu memahami untuk kuiz.
Jadi jika anda mempunyai soalan kepada mereka, anda boleh meminta mereka sekarang.
Tetapi ini akan menjadi sangat diterajui pelajar sesi di mana anda semua bertanya soalan,
jadi diharapkan orang mempunyai soalan.
Adakah sesiapa yang mempunyai soalan?
Ya. >> [Pelajar] Bolehkah anda pergi lebih petunjuk lagi?
Saya akan pergi lebih petunjuk.
Semua pembolehubah anda semestinya hidup dalam ingatan,
tetapi biasanya anda tidak bimbang tentang itu dan anda hanya mengatakan x + 2 dan y + 3
dan pengkompil akan memikirkan di mana perkara-perkara yang hidup untuk anda.
Apabila anda berurusan dengan petunjuk, sekarang anda jelas menggunakan alamat memori.
Jadi pembolehubah tunggal akan hanya pernah tinggal di alamat tunggal pada bila-bila masa yang diberikan.
Jika kita mahu mengisytiharkan penunjuk, apa yang jenis akan kelihatan seperti?
>> Saya mahu mengisytiharkan p penunjuk. Apakah jenis kelihatan seperti?
[Pelajar] int * p. >> Yeah. Jadi int * p.
Dan bagaimana saya boleh membuat ia menunjukkan x? >> [Pelajar] Ampersand.
[Bowden] Jadi #: glib benar-benar dipanggil alamat pengendali.
Jadi, apabila saya katakan & x ia mendapat alamat ingatan x berubah-ubah.
Jadi sekarang saya mempunyai p penunjuk, dan di mana-mana sahaja dalam kod saya, saya boleh menggunakan p *
atau saya boleh menggunakan x dan ia akan menjadi perkara yang sama yang tepat.
(* P). Apakah ini lakukan? Apakah bintang yang bermakna?
[Pelajar] Ia bermaksud nilai pada ketika itu. >> Yeah.
Jadi, jika kita melihat ia, ia boleh menjadi sangat berguna untuk menarik keluar gambar rajah
di mana ini adalah kotak sedikit memori untuk x, yang berlaku mempunyai nilai 4,
maka kita mempunyai kotak sedikit memori untuk p,
dan sebagainya p mata x, jadi kita lukiskan anak panah dari p ke x.
Jadi, apabila kita katakan p * kita mengatakan pergi ke kotak yang p.
Bintang adalah mengikuti anak panah dan kemudian melakukan apa sahaja yang anda mahu dengan kotak yang di sana.
Jadi saya boleh katakan * p = 7; dan yang akan pergi ke kotak yang x dan perubahan yang ke 7.
Atau saya boleh mengatakan int z = * p * 2; Itu mengelirukan kerana bintang itu, bintang.
Bintang satu dereferencing p, bintang lain mendarabkan dengan 2.
Notis saya boleh mempunyai hanya serta menggantikan p * dengan x.
Anda boleh menggunakan mereka dengan cara yang sama.
Dan kemudian pada saya boleh mempunyai titik p untuk perkara yang benar-benar baru.
Saya hanya boleh mengatakan p = &z;
Jadi sekarang p ada mata lagi x; ia menunjuk ke z.
Dan bila-bila masa yang saya lakukan p * ia sama seperti melakukan z.
Jadi perkara yang berguna tentang ini ialah apabila kita mula masuk ke fungsi.
>> Ia adalah jenis sia-sia untuk mengisytiharkan penunjuk bahawa mata kepada sesuatu
dan kemudian anda hanya dereferencing ia
apabila anda boleh menggunakan pembolehubah asal untuk memulakan dengan.
Tetapi apabila anda mendapat ke dalam fungsi - jadi mari kita mengatakan bahawa kita mempunyai beberapa fungsi, int foo,
yang mengambil penunjuk dan hanya tidak * p = 6;
Seperti yang kita lihat sebelum ini dengan swap, anda tidak boleh melakukan swap yang berkesan dan fungsi yang berasingan
dengan hanya lulus integer kerana segala-galanya dalam C sentiasa lulus oleh nilai.
Malah apabila anda lulus petunjuk anda lulus oleh nilai.
Ia hanya kebetulan bahawa nilai-nilai adalah alamat ingatan.
Jadi apabila saya mengatakan foo (p), saya lulus penunjuk ke foo fungsi
dan kemudian foo melakukan * p = 6;
Jadi di dalam fungsi itu, * p masih bersamaan dengan x,
tetapi saya tidak boleh menggunakan x di dalam fungsi itu kerana ia tidak scoped dalam fungsi itu.
Jadi * p = 6 adalah satu-satunya cara saya boleh mengakses pembolehubah tempatan dari fungsi yang lain.
Atau, baik, petunjuk-satunya cara saya boleh mengakses pembolehubah tempatan dari fungsi yang lain.
[Pelajar] Mari kita mengatakan anda mahu untuk kembali penunjuk. Bagaimana sebenarnya yang anda lakukan?
[] Bowden Return penunjuk seperti sesuatu seperti int y = 3; pulangan & y? >> [Pelajar] Yeah.
[Bowden] Okay. Anda tidak perlu melakukan ini. Ini adalah buruk.
Saya fikir saya melihat dalam slaid kuliah anda mula melihat ini seluruh rajah memori
di mana di sini anda telah mendapat alamat ingatan 0
dan turun di sini anda mempunyai alamat ingatan 4 gig atau 2 hingga 32.
Jadi maka anda telah mendapat beberapa barangan dan barangan beberapa dan kemudian anda mempunyai timbunan anda
dan anda telah mendapat timbunan anda, yang anda hanya mula belajar tentang, membesar.
[Pelajar] Bukankah timbunan di atas timbunan?
>> Yeah. Timbunan itu di atas, ia tidak? >> [Pelajar] Nah, dia meletakkan 0 di atas.
[Pelajar] Oh, dia meletakkan 0 di atas. >> [Pelajar] Oh, okay.
Penafian: Anywhere dengan CS50 anda akan melihat ia cara ini. >> [Pelajar] Okay.
Ia hanya bahawa apabila anda pertama kali melihat susunan,
seperti apabila anda memikirkan timbunan anda berfikir menyusun perkara-perkara di atas satu sama lain.
Jadi, kita cenderung untuk flip ini sekitar supaya timbunan membesar seperti timbunan biasanya akan
bukan timbunan tergantung ke bawah. >> [Pelajar] Jangan timbunan teknikal membesar juga, walaupun?
Ia bergantung kepada apa yang anda maksudkan dengan membesar.
Timbunan dan longgokan sentiasa berkembang dalam arah yang bertentangan.
Timbunan sentiasa membesar dalam erti kata bahawa ia membesar
ke arah alamat-alamat ingatan yang lebih tinggi, dan timbunan itu berkembang ke bawah
bahawa ia berkembang ke arah alamat-alamat ingatan yang lebih rendah.
Jadi atas adalah 0 dan bawah adalah alamat memori yang tinggi.
Mereka kedua-dua semakin meningkat, hanya dalam menentang arahan.
[Pelajar] saya hanya bermakna bahawa kerana anda berkata anda meletakkan timbunan di bahagian bawah
kerana ia seolah-olah lebih intuitif kerana untuk timbunan untuk memulakan di bahagian atas timbunan,
timbunan di atas dirinya terlalu, jadi that's - >> Yeah.
Anda juga berfikir timbunan sebagai membesar dan lebih besar, tetapi timbunan lebih-lebih lagi.
Jadi tindanan adalah salah satu yang kita jenis mahu menunjukkan membesar.
Tetapi di mana-mana anda melihat sebaliknya akan menunjukkan alamat 0 di atas
dan alamat ingatan yang tertinggi di bahagian bawah, jadi ini adalah pandangan biasa anda memori.
>> Adakah anda mempunyai soalan?
[Pelajar] Bolehkah anda memberitahu kami lebih lanjut mengenai timbunan itu?
Yeah. Saya akan sampai ke dalam kedua.
Pertama, akan kembali kepada mengapa kembali & y adalah satu perkara yang buruk,
pada timbunan anda mempunyai sekumpulan bingkai tindanan yang mewakili semua fungsi-fungsi
yang telah dipanggil.
Jadi mengabaikan perkara sebelumnya, atas timbunan anda sentiasa akan menjadi fungsi utama
kerana itulah fungsi pertama yang dipanggil.
Dan kemudian apabila anda memanggil fungsi yang lain, timbunan akan berkembang ke bawah.
Jadi jika saya memanggil beberapa fungsi, foo, dan ia mendapat bingkai tindanan sendiri,
ia boleh memanggil beberapa fungsi, bar; ia mendapat bingkai tindanan sendiri.
Dan bar boleh rekursi dan ia boleh memanggil dirinya,
dan supaya panggilan kedua ke bar akan untuk mendapatkan bingkai tindanan sendiri.
Dan jadi apa yang berlaku dalam bingkai tindanan adalah semua pembolehubah tempatan
dan semua hujah fungsi yang -
Mana-mana perkara yang tempatan scoped untuk fungsi ini pergi dalam bingkai tindanan.
Supaya bermakna apabila saya berkata sesuatu seperti bar adalah fungsi,
Saya hanya akan mengisytiharkan integer dan kemudian kembali penunjuk kepada integer itu.
Jadi di manakah y hidup?
[Pelajar] y tinggal di bar. >> [Bowden] Yeah.
Di suatu tempat di dataran ini sedikit memori adalah persegi littler yang mempunyai y di dalamnya.
Apabila saya kembali & y, saya kembali penunjuk untuk blok ini sedikit ingatan.
Tetapi kemudian apabila fungsi pulangan, bingkai tindanan mendapat muncul dari timbunan.
Dan itulah sebabnya ia dipanggil timbunan.
Ia seperti struktur data timbunan, jika anda tahu apa yang.
Atau pun seperti timbunan dulang sentiasa contoh,
utama akan pergi di bahagian bawah, maka fungsi pertama yang anda panggil akan pergi di atas itu,
dan anda tidak boleh mendapatkan kembali ke utama sehingga anda kembali dari semua fungsi yang telah dipanggil
yang telah diletakkan di atasnya.
>> [Pelajar] Jadi jika anda tidak melakukan kembali y &, nilai itu adalah tertakluk kepada perubahan tanpa notis.
Ya, it's - >> [pelajar] Ia boleh ditulis ganti. >> Yeah.
Ia adalah benar-benar - Jika anda cuba dan -
Ini juga akan menjadi sebuah bar * int kerana ia kembali penunjuk,
jadi jenis pulangan adalah int *.
Jika anda cuba untuk menggunakan nilai pulangan fungsi ini, ia adalah tingkah laku undefined
kerana penunjuk yang menunjuk ke memori buruk. >> [Pelajar] Okay.
Jadi apa jika, sebagai contoh, anda mengisytiharkan int * y = malloc (sizeof (int))?
Itulah yang lebih baik. Ya.
[Pelajar] Kita bercakap tentang bagaimana apabila kita mengheret perkara ke tong kitar semula kami
mereka sebenarnya tidak dipadamkan; kita hanya kehilangan petunjuk mereka.
Jadi dalam kes ini adakah kita sebenarnya memadam nilai atau ia masih ada dalam ingatan?
Bagi sebahagian besar, ia akan masih berada di sana.
Tetapi mari kita mengatakan bahawa kita berlaku untuk memanggil beberapa fungsi lain, Baz.
Baz akan untuk mendapatkan bingkai tindanan sendiri di sini.
Ia akan penggantian semua barangan ini,
dan kemudian jika anda kemudian cuba menggunakan penunjuk yang anda mendapat sebelum,
ia tidak akan menjadi nilai yang sama.
Ia akan telah berubah hanya kerana anda dipanggil Baz fungsi.
[Pelajar] Tetapi sekiranya kita tidak akan kita masih mendapat 3?
[Bowden] Dalam semua kemungkinan, anda akan.
Tetapi anda tidak boleh bergantung kepada itu. C hanya berkata tingkah laku undefined.
>> [Pelajar] Oh, ia tidak. Okay.
Jadi, apabila anda mahu untuk kembali penunjuk, ini adalah di mana malloc datang dalam digunakan.
Saya menulis sebenarnya hanya kembali malloc (3 * sizeof (int)).
Kami akan pergi lebih malloc lebih dalam kedua, tetapi idea malloc semua pembolehubah tempatan anda
selalu pergi pada timbunan.
Apa sahaja yang malloced pergi pada timbunan, dan ia selama-lamanya dan akan sentiasa pada timbunan
sehingga anda dengan jelas membebaskan ia.
Jadi ini bermakna bahawa apabila anda malloc sesuatu, ia akan terus hidup selepas pulangan fungsi.
[Pelajar] ia akan bertahan selepas program berhenti berjalan? >> No.
Okay, jadi ia akan berada di sana sehingga program ini adalah semua cara yang dilakukan berjalan. >> Ya.
Kita boleh pergi ke butir-butir apa yang berlaku apabila program ini berhenti berjalan.
Anda mungkin perlu untuk mengingatkan saya, tetapi itu adalah satu perkara yang berasingan sepenuhnya.
[Pelajar] Jadi malloc mewujudkan penunjuk? >> Yeah.
Malloc - >> [pelajar] saya fikir malloc menandakan blok memori yang penunjuk boleh menggunakan.
[Bowden] Saya mahu rajah itu lagi. >> [Pelajar] Jadi fungsi ini berfungsi, walaupun?
[Pelajar] Yeah, malloc menandakan blok memori yang anda boleh gunakan,
dan kemudian ia kembali alamat blok memori yang pertama.
>> [Bowden] Yeah. Jadi apabila anda malloc, anda meraih beberapa blok memori
yang sedang dalam timbunan.
Jika timbunan itu terlalu kecil, maka timbunan itu hanya akan berkembang, dan ia tumbuh ke arah ini.
Jadi mari kita mengatakan timbunan itu terlalu kecil.
Maka ia adalah kira-kira untuk berkembang sedikit dan kembali penunjuk kepada blok ini yang hanya meningkat.
Apabila anda barangan percuma, anda membuat lebih banyak ruang dalam timbunan,
demikian maka kemudian memanggil malloc boleh menggunakan semula bahawa memori yang anda sebelum ini telah dibebaskan.
Perkara penting mengenai malloc dan bebas adalah bahawa ia memberi anda kawalan sepenuhnya
sepanjang hayat blok-blok memori.
Pembolehubah global adalah sentiasa hidup.
Pembolehubah tempatan hidup dalam skop mereka.
Secepat anda pergi lalu bersedia kerinting, pembolehubah tempatan mati.
Memori Malloced adalah hidup apabila anda mahu ia hidup
dan kemudian dikeluarkan apabila anda memberitahu ia akan dikeluarkan.
Mereka sebenarnya hanya 3 jenis memori, benar-benar.
Ada pengurusan memori automatik, yang merupakan timbunan.
Perkara yang berlaku untuk anda secara automatik.
Apabila anda mengatakan int x, memori diperuntukkan bagi x int.
Apabila x padam skop, memori ditebusguna bagi x.
Kemudian terdapat pengurusan memori dinamik, yang adalah apa yang malloc,
yang adalah apabila anda mempunyai kawalan.
Anda dinamik memutuskan apabila memori harus dan tidak harus diperuntukkan.
Dan kemudian ada yang statik, yang hanya bermakna bahawa ia hidup selama-lamanya,
yang merupakan apa pembolehubah global.
Mereka hanya sentiasa dalam ingatan.
>> Soalan?
[Pelajar] Bolehkah anda menentukan blok hanya dengan menggunakan pendakap kerinting
tetapi tidak perlu mempunyai? jika pernyataan atau kenyataan sementara atau apa-apa seperti itu.
Anda boleh menentukan blok seperti dalam fungsi, tetapi yang mempunyai kerinting pendakap terlalu.
[Pelajar] Jadi anda tidak boleh hanya mempunyai seperti sepasang pendakap kerinting rawak dalam kod anda
yang mempunyai pembolehubah tempatan? >> Ya, anda boleh.
Inside bar int kita boleh mempunyai {int y = 3;}.
Itu sepatutnya menjadi hak di sini.
Tetapi yang benar-benar mentakrifkan skop int y.
Selepas bahawa pendakap kerinting kedua, y tidak boleh digunakan lagi.
Anda hampir tidak pernah berbuat demikian, walaupun.
Mendapatkan kembali kepada apa yang berlaku apabila program berakhir,
ada jenis dusta tanggapan / setengah yang kita berikan dalam usaha untuk hanya membuat perkara yang mudah.
Kami memberitahu anda bahawa apabila anda memperuntukkan memori
anda memperuntukkan beberapa Sebahagian RAM bagi pemboleh ubah itu.
Tetapi anda tidak benar-benar langsung menyentuh RAM pernah dalam program anda.
Jika anda berfikir tentang hal itu, bagaimana saya menarik -
Dan sebenarnya, jika anda pergi melalui dalam GDB anda akan melihat perkara yang sama.
Tidak kira berapa kali anda menjalankan program anda atau apa program yang anda menjalankan,
timbunan sentiasa akan bermula -
anda sentiasa akan melihat pembolehubah sekitar sesuatu oxbffff alamat.
Ia biasanya tempat di rantau itu.
Tetapi bagaimana boleh 2 program mungkin mempunyai petunjuk untuk memori yang sama?
[Pelajar] Terdapat beberapa jawatan sewenang-wenangnya mana oxbfff sepatutnya pada RAM
yang sebenarnya boleh berada di tempat-tempat yang berbeza-beza apabila fungsi dipanggil.
Yeah. Istilah ini adalah ingatan maya.
Idea ini adalah bahawa setiap proses tunggal, setiap program tunggal yang sedang berjalan pada komputer anda
mempunyai sendiri - mari kita andaikan 32 bit alamat benar-benar bebas ruang.
Ini adalah ruang alamat.
Ia mempunyai sendiri yang benar-benar bebas 4 gigabait untuk digunakan.
>> Jadi, jika anda menjalankan 2 program serentak, program ini melihat 4 gigabait kepada dirinya,
program ini melihat 4 gigabait untuk dirinya sendiri,
dan ia adalah mustahil untuk program ini untuk dereference penunjuk
dan akhirnya dengan memori daripada program ini.
Dan apa memori maya adalah pemetaan daripada ruang alamat proses
kepada perkara-perkara sebenar pada RAM.
Jadi ia terpulang kepada sistem operasi anda untuk mengetahui bahawa,
hey, apabila ini lelaki dereferences penunjuk oxbfff, yang benar-benar bermakna
bahawa dia mahu RAM bait 1000,
sedangkan jika ini oxbfff dereferences program, dia benar-benar mahu RAM bait 10000.
Mereka boleh sewenang-wenangnya jauh.
Ini adalah lebih benar perkara dalam ruang proses alamat tunggal.
Jadi seperti ia melihat semua 4 gigabait untuk dirinya sendiri, tetapi katakan -
[Pelajar] Adakah setiap proses tunggal -
Katakan anda mempunyai komputer dengan hanya 4 gigabait RAM.
Adakah setiap proses tunggal melihat keseluruhan 4 gigabait? >> Ya.
Tetapi 4 gigabait ia melihat adalah satu pembohongan.
Ia hanya ia berpendapat ia mempunyai semua memori ini kerana ia tidak tahu apa-apa proses lain wujud.
Ia hanya akan menggunakan memori yang banyak seperti ia sebenarnya perlu.
Sistem operasi tidak akan memberi RAM kepada proses ini
jika ia tidak menggunakan apa-apa memori di seluruh rantau ini.
Ia tidak akan memberikan memori untuk rantau itu.
Tetapi idea bahawa - saya cuba untuk berfikir - saya tidak boleh berfikir satu analogi.
Analogi sukar.
Salah satu daripada isu-isu memori maya atau salah satu daripada perkara-perkara yang ia menyelesaikan
adalah bahawa proses harus menyedari sepenuhnya antara satu sama lain.
Dan supaya anda boleh menulis mana-mana program yang hanya dereferences penunjuk mana-mana,
suka hanya menulis satu program yang mengatakan * (ox1234),
dan bahawa memori dereferencing alamat 1234.
>> Tetapi ia terpulang kepada sistem operasi kemudian menterjemahkan apa 1234 cara.
Jadi, jika 1234 berlaku untuk menjadi alamat ingatan yang sah untuk proses ini,
seperti ia pada timbunan atau sesuatu, maka ini akan memulangkan nilai alamat memori yang
setakat sebagai proses tahu.
Tetapi jika 1234 bukan alamat yang sah, seperti ia berlaku kepada tanah
dalam sekeping beberapa sedikit ingatan di sini bahawa adalah di luar timbunan dan seterusnya timbunan itu
dan anda tidak benar-benar digunakan, maka itulah apabila anda mendapatkan perkara-perkara seperti segfaults
kerana anda menyentuh memori yang anda tidak perlu menyentuh.
Ini juga benar -
Satu sistem 32-bit, 32-bit bermakna anda mempunyai 32 bit untuk menentukan alamat ingatan.
Ia itulah petunjuk 8 bait kerana 32 bit 8 bait - atau 4 bait.
Penunjuk 4 bait.
Jadi, apabila anda melihat penunjuk seperti oxbfffff, iaitu: -
Dalam mana-mana program yang diberikan anda hanya boleh membina apa-apa penunjuk sewenang-wenangnya,
mana-mana dari ox0 untuk lembu 8 f's - ffffffff.
[Pelajar] Tidakkah kamu katakan mereka 4 bait? >> Yeah.
[Pelajar] Kemudian bait masing-masing akan mempunyai - >> [Bowden] Perenambelasan.
Perenambelasan - 5, 6, 7, 8. Jadi petunjuk anda akan sentiasa melihat dalam perenambelasan.
Ia hanya bagaimana kita mengklasifikasikan petunjuk.
Setiap 2 digit perenambelasan adalah 1 bait.
Jadi ada akan menjadi 8 digit perenambelasan untuk 4 bait.
Jadi setiap penunjuk tunggal pada sistem 32-bit akan menjadi 4 bait,
yang bermaksud bahawa dalam proses anda, anda boleh membina apa-apa sewenang-wenangnya 4 bait
dan membuat penunjuk daripada itu,
yang bermaksud bahawa sejauh ia sedar, ia boleh menangani keseluruhan tempoh 2 32 bait memori.
Walaupun ia tidak benar-benar mempunyai akses kepada,
walaupun komputer anda hanya mempunyai 512 megabait, ia berpendapat ia mempunyai memori yang banyak.
Dan sistem operasi pintar cukup bahawa ia hanya akan memperuntukkan apa yang anda benar-benar perlu.
Ia tidak hanya pergi, oh, proses baru: 4 gig.
>> Yeah. >> [Pelajar] Apakah lembu bermakna? Mengapa anda menulis?
Ia hanya simbol bagi perenambelasan.
Apabila anda melihat permulaan nombor dengan lembu, perkara berturut perenambelasan.
[Pelajar] Anda telah menjelaskan tentang apa yang berlaku apabila program berakhir. >> Ya.
Apa yang berlaku apabila program berakhir adalah sistem operasi
hanya memadamkan pemetaan bahawa ia mempunyai untuk alamat ini, dan itu sahaja.
Sistem operasi kini boleh hanya memberi ingatan bahawa program lain untuk digunakan.
[Pelajar] Okay.
Jadi, apabila anda memperuntukkan sesuatu pada timbunan atau pembolehubah timbunan atau global atau apa-apa,
mereka semua hanya hilang secepat program berakhir
kerana sistem operasi kini bebas untuk memberi ingatan itu kepada apa-apa proses lain.
[Pelajar] Walaupun mungkin masih terdapat nilai-nilai yang ditulis dalam? >> Yeah.
Nilai-nilai yang mungkin masih ada.
Ia hanya ia akan menjadi sukar untuk mendapatkan mereka.
Ia adalah lebih sukar untuk mendapatkan mereka daripada ia adalah untuk mendapatkan sekurang-fail dipadam
kerana jenis fail yang dipadam daripada duduk di sana untuk masa yang lama dan cakera keras adalah lebih besar.
Jadi ia akan overwrite bahagian yang berlainan memori
sebelum ia berlaku menimpa sebahagian ingatan bahawa fail yang digunakan untuk berada di.
Tetapi ingatan utama, RAM, anda kitaran melalui banyak yang lebih cepat,
jadi ia akan sangat cepat ditindih.
Soalan ini atau apa-apa lagi?
[Pelajar] Saya mempunyai soalan mengenai topik yang berbeza. >> Okay.
Adakah sesiapa yang mempunyai soalan mengenai perkara ini?
>> Okay. Topik yang berbeza. >> [Pelajar] Okay.
Saya akan melalui beberapa ujian amalan,
dan salah seorang daripada mereka, ia bercakap tentang sizeof
dan nilai bahawa ia kembali atau jenis yang berubah-ubah. >> Ya.
Dan ia berkata bahawa kedua-dua int dan panjang kedua-dua pulangan 4, jadi mereka kedua-dua 4 bait panjang.
Adakah terdapat sebarang perbezaan di antara int dan panjang, atau adakah ia perkara yang sama?
Ya, terdapat perbezaan.
C standard -
Saya mungkin akan merosakkan.
Standard C adalah sama seperti apa yang C, dokumentasi rasmi C.
Ini adalah apa yang dikatakannya.
Jadi standard C hanya mengatakan bahawa char selama-lamanya dan akan sentiasa menjadi 1 bait.
Segala-galanya selepas itu - pendek sentiasa hanya ditakrifkan sebagai lebih besar daripada atau sama kepada char.
Ini mungkin tegas lebih besar daripada, tetapi tidak positif.
Int hanya ditakrifkan sebagai lebih besar daripada atau sama pendek.
Dan yang lama hanya ditakrifkan sebagai lebih besar daripada atau sama dengan int.
Dan yang lama adalah lebih besar atau sama dengan yang lama.
Jadi satu-satunya perkara standard C mentakrifkan adalah pesanan relatif segala-galanya.
Jumlah sebenar memori bahawa perkara-perkara yang mengambil umumnya sehingga pelaksanaan,
tetapi ia cukup ditakrifkan dengan baik pada ketika ini. >> [Pelajar] Okay.
Jadi seluar pendek hampir sentiasa akan menjadi 2 bait.
Ints hampir sentiasa akan menjadi 4 bait.
Long Long hampir sentiasa akan menjadi 8 bait.
Dan Roh meronta-ronta, ia bergantung kepada sama ada anda menggunakan 32-bit atau sistem 64-bit.
Jadi panjang akan sesuai dengan jenis sistem.
Jika anda menggunakan sistem 32-bit seperti Peralatan ini, ia akan menjadi 4 bait.
Jika anda menggunakan 64-bit seperti banyak komputer kebelakangan ini, ia akan menjadi 8 bait.
>> Ints adalah hampir sentiasa 4 bait pada ketika ini.
Long Long adalah hampir sentiasa 8 bait.
Pada masa lalu, ints digunakan untuk hanya menjadi 2 bait.
Tetapi melihat bahawa ini benar-benar memenuhi semua hubungan ini lebih besar daripada dan sama dengan.
Selagi sempurna dibenarkan untuk menjadi saiz yang sama seperti integer,
dan ia juga dibenarkan untuk menjadi saiz yang sama seperti yang lama.
Dan ia hanya kebetulan bahawa dalam 99,999% sistem, ia akan menjadi sama dengan
sama ada int atau lama. Ia hanya bergantung kepada 32-bit atau 64-bit. >> [Pelajar] Okay.
Dalam terapung, bagaimana adalah titik perpuluhan yang ditetapkan dari segi bit?
Seperti sebagai binari? >> Yeah.
Anda tidak perlu tahu bahawa bagi CS50.
Anda bahkan tidak mengetahui bahawa pada tahun 61.
Anda tidak mengetahui bahawa benar-benar dalam mana-mana kursus.
Ia hanya gambaran.
Saya lupa perumpukan bit tepat.
Idea titik terapung adalah bahawa anda memperuntukkan sejumlah tertentu bit untuk mewakili -
Pada asasnya, segala-galanya adalah dalam notasi saintifik.
Jadi anda memperuntukkan bilangan tertentu bit untuk mewakili nombor itu sendiri, seperti 1,2345.
Saya tidak boleh mewakili nombor dengan angka yang lebih daripada 5.
Kemudian anda juga memperuntukkan satu bilangan tertentu bit supaya ia cenderung untuk menjadi seperti
anda hanya boleh pergi sehingga kepada bilangan tertentu, seperti itulah eksponen terbesar anda boleh mempunyai,
dan anda hanya boleh pergi ke eksponen tertentu,
seperti itulah eksponen terkecil anda boleh mempunyai.
>> Saya tidak ingat cara bit tepat diberikan kepada semua nilai-nilai ini,
tetapi sebilangan bit didedikasikan kepada 1,2345,
lain sebilangan bit khusus untuk eksponen,
dan ia hanya mungkin untuk mewakili eksponen saiz tertentu.
[Pelajar] Dan double? Adakah itu seperti apungan yang lebih panjang? >> Yeah.
Ia adalah perkara yang sama sebagai apungan kecuali sekarang anda menggunakan 8 bait bukannya daripada 4 bait.
Sekarang anda akan dapat untuk menggunakan 9 digit atau 10 digit,
dan ini akan mampu untuk pergi ke 300 dan bukannya 100. >> [Pelajar] Okay.
Dan terapung juga 4 bait. >> Ya.
Nah, sekali lagi, ia mungkin bergantung keseluruhan mengenai pelaksanaan am,
tetapi terapung 4 bait, beregu 8.
Doubles dipanggil dua kali ganda kerana mereka adalah dua kali ganda saiz terapung.
[Pelajar] Okay. Dan ada dua kali ganda beregu? >> Tidak.
Saya fikir - >> [pelajar] Seperti Long lama? >> Yeah. Saya tidak fikir begitu. Ya.
[Pelajar] Pada ujian tahun lepas terdapat soalan tentang fungsi utama
perlu menjadi sebahagian daripada program anda.
Jawapannya adalah bahawa ia tidak perlu untuk menjadi sebahagian daripada program anda.
Dalam apa keadaan? Itulah apa yang saya lihat.
[Bowden] Nampaknya - >> [pelajar] Apa keadaan?
Adakah anda mempunyai masalah? >> [Pelajar] Ya, saya pasti boleh tarik sehingga ia.
Ia tidak perlu, teknikal, tetapi pada dasarnya ia akan menjadi.
[Pelajar] saya nampak salah pada yang berbeza tahun ini.
Ia adalah seperti Benar atau Palsu: A sah - >> Oh, fail c.?
[Pelajar] Sebarang fail c mesti mempunyai - [kedua-dua bercakap pada sekali difahami]
Okay. Jadi yang berasingan.
>> Sebuah fail c hanya perlu mengandungi fungsi.
Anda boleh menyusun fail ke dalam kod mesin, binari, apa jua,
tanpa ia menjadi laku lagi.
A laku yang sah mestilah mempunyai fungsi utama.
Anda boleh menulis 100 fungsi dalam 1 fail tetapi tidak utama
dan kemudian menyusun yang turun kepada perduaan,
maka anda menulis fail yang lain hanya mempunyai utama tetapi ia memerlukan sekumpulan fungsi ini
dalam fail ini perduaan di sini.
Dan supaya apabila anda membuat laku, bahawa apa yang dilakukan oleh pemaut
ia menggabungkan 2 fail binari ke laksana.
Jadi fail c tidak perlu untuk mempunyai fungsi utama pada semua.
Dan pada asas kod besar, anda akan melihat beribu-ribu c fail dan 1 file utama.
Lebih banyak soalan?
[Pelajar] Ada satu lagi soalan.
Ia berkata buat ialah pengkompil. Benar atau Palsu?
Dan jawapannya adalah palsu, dan saya memahami mengapa ia tidak seperti dilafaz.
Tetapi apa yang kita panggil membuat jika ia tidak?
Membuat adalah pada dasarnya hanya - saya boleh melihat apa yang ia memanggilnya.
Tetapi ia hanya menjalankan arahan.
Membuat.
Saya boleh tarik sehingga ini. Yeah.
Oh, ya. Buat juga tidak bahawa.
Ini mengatakan tujuan utiliti membuat adalah untuk menentukan secara automatik
yang keping program besar perlu recompiled
dan mengeluarkan arahan kepada susun semula mereka.
Anda boleh membuat membuat fail yang benar-benar besar.
Buat kelihatan pada setem masa fail dan, seperti yang kita katakan sebelum ini,
anda boleh menyusun fail individu, dan ia tidak sehingga anda sampai ke pemaut
bahawa mereka sedang meletakkan bersama-sama ke dalam laksana.
Jadi jika anda mempunyai 10 fail yang berbeza dan anda membuat perubahan kepada 1 daripada mereka,
maka apa yang membuat akan lakukan adalah hanya susun semula 1 fail
dan kemudian relink semua bersama-sama.
Tetapi ia lebih dumber daripada itu.
Ia terpulang kepada anda untuk benar-benar menentukan bahawa itulah apa yang ia harus lakukan.
Ia secara lalai mempunyai keupayaan untuk mengenali barangan ini masa setem,
tetapi anda boleh menulis fail membuat untuk berbuat apa-apa.
Anda boleh menulis membuat fail supaya apabila anda menaip membuat ia hanya cd ke direktori lain.
Saya telah semakin kecewa kerana saya jelujur segala-galanya di dalam Appliance saya
dan kemudian saya melihat PDF dari Mac.
>> Jadi saya pergi kepada Finder dan saya boleh Pergi, Sambung ke Server,
dan pelayan saya menyambung ke Appliance saya, dan kemudian saya membuka PDF
yang mendapat disusun oleh LaTeX.
Tetapi saya telah semakin kecewa kerana setiap kali tunggal saya yang diperlukan untuk menyegarkan PDF,
Saya terpaksa menyalin ke direktori tertentu bahawa ia boleh mengakses
dan ia semakin menjengkelkan.
Jadi sebaliknya saya menulis fail membuat, yang anda perlu menentukan bagaimana ia membuat perkara.
Bagaimana anda membuat ini adalah PDF LaTeX.
Sama seperti fail membuat mana-mana - Saya rasa anda tidak pernah melihat fail membuat,
tetapi kita mempunyai dalam Appliance fail membuat global yang hanya berkata,
jika anda menyusun fail C, gunakan dilafaz.
Dan sebagainya di sini dalam fail membuat saya bahawa saya membuat saya katakan,
fail ini, anda akan mahu untuk menyusun dengan LaTeX PDF.
Dan supaya ia LaTeX PDF yang melakukan menyusun.
Buat tidak menyusun. Ia hanya menjalankan arahan ini dalam urutan yang saya sebutkan.
Jadi ia berjalan PDF LaTeX, ia salinan direktori saya mahu ia akan disalin ke,
ia cd ke direktori dan melakukan perkara-perkara lain,
tetapi ia mengiktiraf apabila perubahan fail,
dan jika ia berubah, maka ia akan berjalan arahan bahawa ia sepatutnya untuk menjalankan
apabila perubahan fail. >> [Pelajar] Okay.
Saya tidak tahu di mana fail membuat global bagi saya untuk check it out.
Soalan-soalan lain? Apa-apa sahaja dari masa lalu kuiz? Apa-apa perkara penunjuk?
Terdapat perkara-perkara yang halus dengan petunjuk seperti -
Saya tidak akan dapat untuk mencari soalan kuiz di atasnya -
tetapi hanya seperti jenis ini perkara.
Pastikan anda memahami bahawa apabila saya mengatakan int * x * y -
Ini tidak betul-betul apa-apa di sini, saya rasa.
Tetapi seperti * x * y, mereka adalah 2 pembolehubah yang pada timbunan.
Bila saya katakan x = malloc (sizeof (int)), x ialah masih pembolehubah pada timbunan,
malloc adalah beberapa blok lebih dalam timbunan itu, dan kita mempunyai titik x kepada timbunan.
>> Jadi sesuatu pada mata timbunan kepada timbunan.
Apabila anda malloc apa-apa, anda pasti menyimpan ia di dalam penunjuk.
Jadi penunjuk bahawa pada timbunan, blok malloced pada timbunan.
Ramai orang mendapat keliru dan mengatakan int * x = malloc, x ialah pada timbunan.
No Apa x menunjuk ke pada timbunan.
x itu sendiri adalah pada timbunan, melainkan jika atas apa jua sebab anda telah x menjadi pembolehubah global,
di mana ia berlaku untuk menjadi di rantau lain memori.
Jadi mengesan, ini gambar rajah kotak dan anak panah adalah agak biasa bagi kuiz.
Atau jika ia tidak kuiz 0, ia akan menjadi kuiz 1.
Anda perlu tahu semua ini, langkah-langkah dalam menyusun
kerana anda terpaksa menjawab soalan-soalan kepada orang-orang. Ya.
[Pelajar] Bolehkah kita pergi ke langkah-langkah - >> Pasti.
Sebelum langkah-langkah dan menyusun kita mempunyai prapemprosesan,
menyusun, memasang, dan menghubungkan.
Prapemprosesan. Apakah yang melakukan?
Ia adalah langkah yang paling mudah di - baik, tidak seperti -
itu tidak bermakna ia harus jelas, tetapi ia adalah langkah yang paling mudah.
Kalian boleh melaksanakan diri sendiri. Yeah.
[Pelajar] Ambil apa yang anda mempunyai dalam anda termasuk seperti ini dan ia salinan dan kemudian juga mentakrifkan.
Ia kelihatan untuk perkara-perkara seperti # include dan # menentukan,
dan ia hanya salinan dan Pes apa yang mereka sebenarnya bermakna.
Jadi, apabila anda mengatakan # include cs50.h, prapemproses adalah menyalin dan menampal cs50.h
ke dalam barisan itu.
Apabila anda mengatakan # define x menjadi 4, prapemproses pergi melalui keseluruhan program
dan menggantikan semua kejadian x dengan 4.
Jadi prapemproses mengambil fail C yang sah dan output fail C yang sah
mana perkara yang telah disalin dan ditampal.
Jadi sekarang menyusun. Apakah yang melakukan?
[Pelajar] Ia pergi dari C ke binari.
>> [Bowden] Ia tidak pergi sepanjang jalan kepada perduaan.
[Pelajar] Untuk kod mesin kemudian? >> Ia bukan kod mesin.
[Pelajar] Perhimpunan? >> Perhimpunan.
Ia pergi ke Dewan sebelum ia pergi sepanjang jalan kepada kod C,
dan kebanyakan bahasa melakukan sesuatu seperti ini.
Memilih mana-mana bahasa peringkat tinggi, dan jika anda pergi untuk menyusun,
ia adalah mungkin untuk menyusun dalam langkah-langkah.
Pertama, ia akan untuk menyusun Python kepada C, maka ia akan menyusun C ke Perhimpunan,
dan kemudian Perhimpunan akan mendapat diterjemahkan kepada perduaan.
Jadi menyusun akan membawa ia dari C ke Perhimpunan.
Perkataan menyusun biasanya bermakna membawa ia dari peringkat yang lebih tinggi
kepada bahasa pengaturcaraan tahap yang lebih rendah.
Jadi ini adalah langkah sahaja dalam penyusunan di mana anda bermula dengan bahasa peringkat tinggi
dan akhirnya dalam bahasa tahap rendah, dan itulah mengapa langkah dipanggil menyusun.
[Pelajar] Semasa menyusun, mari kita mengatakan bahawa anda telah melakukan # include cs50.h.
Adakah pengkompil susun cs50.h, seperti fungsi yang berada di sana,
dan menterjemahkan ke dalam kod Perhimpunan serta,
atau ia akan menyalin dan tampal sesuatu yang menjadi pra-Perhimpunan?
cs50.h akan cukup banyak tidak pernah berakhir di dalam Dewan.
Perkara seperti prototaip fungsi dan perkara-perkara yang hanya untuk anda berhati-hati.
Ia menjamin bahawa pengkompil boleh menyemak perkara-perkara seperti anda memanggil fungsi
dengan jenis pulangan yang betul dan hujah-hujah yang betul dan barangan.
>> Jadi cs50.h akan preprocessed ke dalam fail, dan kemudian apabila ia menyusun
ia pada asasnya dibuang selepas ia memastikan bahawa segala-galanya yang dipanggil dengan betul.
Tetapi fungsi yang ditakrifkan dalam perpustakaan CS50, yang berasingan daripada cs50.h,
mereka tidak akan disusun secara berasingan.
Itu sebenarnya akan datang ke bawah dalam langkah yang menghubungkan, jadi kami akan sampai ke dalam kedua.
Tetapi pertama, apa yang memasang?
[Pelajar] Perhimpunan binari? >> Yeah.
Menghimpun.
Kami tidak memanggil ia menyusun kerana Perhimpunan adalah cukup banyak terjemahan tulen binari.
Terdapat logik sangat sedikit pergi dari Perhimpunan kepada perduaan.
Ia hanya suka melihat ke atas dalam jadual, oh, kita mempunyai arahan ini;
yang sepadan dengan 01110 binari.
Dan sebagainya fail yang umumnya memasang output fail o.
Dan o fail adalah apa yang kita telah berkata sebelum,
bagaimana fail tidak perlu untuk mempunyai fungsi utama.
Sebarang fail boleh disusun ke fail o selagi ia fail C yang sah.
Ia boleh disusun ke o.
Sekarang, menghubungkan apa yang sebenarnya membawa sekumpulan o fail dan membawa mereka untuk laksana.
Dan sebagainya apa yang menghubungkan tidak boleh anda fikirkan perpustakaan CS50 sebagai fail o.
Ia adalah fail binari yang sudah disusun.
Dan sebagainya apabila anda menyusun fail anda, hello.c anda, yang menyeru GetString,
hello.c mendapat disusun turun ke hello.o,
hello.o kini dalam perduaan.
Ia menggunakan GetString, jadi ia perlu untuk pergi ke cs50.o,
dan pemaut smooshes mereka bersama-sama dan menyalinnya GetString ke fail ini
dan keluar dengan laku yang mempunyai semua fungsi yang diperlukan.
Jadi cs50.o tidak sebenarnya fail O, tetapi ia cukup dekat bahawa tidak ada perbezaan asas.
Jadi menghubungkan hanya membawa sekumpulan fail bersama-sama
yang berasingan mengandungi semua fungsi saya perlu menggunakan
dan mencipta executable yang sebenarnya akan berjalan.
>> Dan supaya juga apa yang kita telah berkata sebelum
mana anda boleh mempunyai 1000. fail c, anda menyusun mereka semua. fail o,
yang mungkin akan mengambil sedikit masa, maka anda menukar 1. fail c.
Anda hanya perlu susun semula bahawa 1 c fail dan kemudian segala-galanya relink lain,
mengaitkan segala-galanya kembali bersama-sama.
[Pelajar] Apabila kita menghubungkan kita menulis lcs50?
Ya, jadi-lcs50. Itu bendera isyarat untuk pemaut yang anda perlu menghubungkan di perpustakaan itu.
Soalan?
Pernahkah kita pergi lebih binari selain bahawa 5 saat dalam syarahan pertama?
Saya tidak fikir begitu.
Anda perlu tahu semua Os besar bahawa kita telah pergi,
dan anda harus mampu, jika kita memberikan anda fungsi,
anda perlu dapat mengatakan ia besar O, kira-kira. Atau baik, besar O adalah kasar.
Jadi, jika anda lihat yang bersarang untuk gelung gelung selama beberapa perkara yang sama,
seperti int i, i <n; int j, j > [pelajar] n kuasa dua. >> Ia cenderung untuk menjadi n kuasa dua.
Jika anda telah tiga bersarang, ia cenderung untuk menjadi n cubed.
Jadi yang jenis perkara yang anda harus dapat menunjukkan dengan serta-merta.
Anda perlu tahu apapun penyisipan dan isih gelembung dan bergabung apapun dan semua orang.
Ia adalah mudah untuk memahami mengapa mereka adalah orang-orang n kuasa dua dan n log n dan semua itu
kerana saya fikir ada kuiz satu tahun di mana kita pada asasnya memberikan anda
pelaksanaan apapun gelembung dan berkata, "Apakah masa menjalankan fungsi ini?"
Jadi, jika anda mengenali ia sebagai sejenis gelembung, maka anda segera boleh mengatakan n kuasa dua.
Tetapi jika anda hanya melihat ia, anda tidak perlu untuk merealisasikan isih gelembung ia;
anda hanya boleh mengatakan ini melakukan ini dan ini. Ini n persegi.
[Pelajar] Adakah terdapat mana-mana contoh yang sukar anda boleh tampil dengan,
seperti idea yang sama memikirkan?
>> Saya tidak fikir kita akan memberikan anda sebarang contoh yang sukar.
Perkara gelembung apapun adalah kira-kira sebagai sukar seperti yang kita akan pergi,
dan juga bahawa, selagi anda memahami bahawa anda iterating lebih array
bagi setiap elemen dalam array, yang akan menjadi sesuatu yang n kuasa dua.
Terdapat soalan umum, seperti di sini kita - Oh.
Hanya pada hari yang lain, Doug mendakwa, "Saya telah mencipta algoritma yang boleh menyusun array
"Nombor n dalam O (log n) masa!"
Jadi bagaimana kita tahu bahawa adalah mustahil?
[Sambutan pelajar didengar] >> Yeah.
Sekurang-kurangnya, anda perlu menyentuh setiap elemen dalam array,
jadi ia adalah mustahil untuk menyelesaikan pelbagai -
Jika segala-galanya adalah dalam perintah Unsorted, maka anda akan menyentuh segala-galanya dalam array,
jadi ia adalah mustahil untuk melakukannya dalam masa kurang daripada O n.
[Pelajar] Anda menunjukkan kepada kita bahawa contoh yang mampu untuk melakukannya di O n
jika anda menggunakan banyak memori. >> Yeah.
Dan that's - saya terlupa apa that's - Adakah ia mengira apapun?
Hmm. Itu adalah satu algoritma isihan integer.
Saya sedang mencari nama khas untuk ini bahawa saya tidak dapat ingat minggu lepas.
Yeah. Ini adalah jenis jenis yang boleh mencapai perkara-perkara yang di besar O n.
Tetapi terdapat batasan, seperti anda hanya boleh menggunakan integer sehingga bilangan tertentu.
Plus jika anda cuba untuk menyelesaikan sesuatu that's -
Jika pelbagai anda adalah 012, -12, 151, 4 juta,
maka bahawa elemen tunggal akan benar-benar merosakkan sorting keseluruhan.
>> Soalan?
[Pelajar] Jika anda mempunyai fungsi rekursi dan ia hanya membuat panggilan rekursi
dalam penyata pulangan, yang ekor rekursi,
dan sebagainya akan yang tidak menggunakan memori yang lebih semasa runtime
atau sekurang-kurangnya akan menggunakan memori setanding sebagai lelaran penyelesaian?
[Bowden] Ya.
Ia mungkin akan menjadi agak perlahan, tetapi tidak benar-benar.
Tail rekursi agak baik.
Melihat sekali lagi pada bingkai tindanan, mari kita mengatakan bahawa kita mempunyai utama
dan kita mempunyai bar int (int x) atau sesuatu.
Ini bukan fungsi rekursi yang sempurna, tetapi pulangan bar (x - 1).
Jadi jelas, ini adalah cacat. Anda perlu kes asas dan barangan.
Tetapi idea di sini adalah bahawa ini adalah ekor rekursi,
yang bermakna apabila bar panggilan utama ia akan mendapatkan bingkai tindanan.
Dalam bingkai tindanan ini terdapat akan menjadi blok memori yang sedikit
yang sepadan ke x hujah.
Dan sebagainya katakan utama berlaku untuk memanggil bar (100);
Jadi x akan bermula sebagai 100.
Jika pengkompil mengiktiraf bahawa ini adalah satu fungsi rekursi ekor,
kemudian apabila bar membuat panggilan rekursi untuk bar,
bukannya membuat bingkai tindanan yang baru, yang mana timbunan mula berkembang sebahagian besarnya,
akhirnya ia akan berjalan ke dalam timbunan itu dan kemudian anda mendapat segfaults
kerana memori bermula berlanggar.
>> Jadi bukannya membuat bingkai tindanan sendiri, ia boleh menyedari,
hey, saya tidak pernah benar-benar perlu untuk kembali kepada bingkai tindanan ini,
jadi sebaliknya saya hanya akan menggantikan hujah ini dengan 99 dan kemudian mula bar seluruh.
Dan kemudian ia akan melakukannya lagi dan ia akan mencapai pulangan bar (x - 1),
dan bukannya membuat bingkai tindanan baru, ia hanya akan menggantikan hujah semasa dengan 98
dan kemudian melompat kembali ke permulaan sangat bar.
Mereka operasi, menggantikan bahawa nilai 1 pada timbunan dan melompat kembali ke permulaan,
cukup berkesan.
Jadi, bukan sahaja ini penggunaan memori yang sama seperti fungsi yang berasingan yang lelaran
kerana anda hanya menggunakan 1 bingkai tindanan, tetapi anda tidak menderita kelemahan
perlu untuk memanggil fungsi.
Memanggil fungsi boleh menjadi agak mahal kerana ia mempunyai kaitan semua persediaan ini
dan teardown dan semua barangan ini.
Jadi ini rekursi ekor adalah baik.
[Pelajar] Mengapa ia tidak mewujudkan langkah-langkah baru?
Kerana ia menyedari ia tidak perlu.
Panggilan ke bar hanya kembali panggilan rekursi.
Jadi ia tidak perlu berbuat apa-apa dengan nilai pulangan.
Ia hanya akan dengan serta-merta mengembalikan.
Jadi ia hanya akan menggantikan hujah sendiri dan mula semula.
Dan juga, jika anda tidak mempunyai versi rekursi ekor,
maka anda mendapat semua ini bar di mana apabila bar ini kembali
ia mempunyai untuk kembali nilainya kepada satu ini, maka bahawa bar segera kembali
dan ia kembali nilainya kepada satu ini, maka ia hanya akan dengan serta-merta mengembalikan
dan kembali nilainya untuk yang satu ini.
Jadi anda menyimpan ini muncul semua perkara-perkara yang jauh daripada timbunan
sejak nilai pulangan hanya akan lulus sepanjang jalan kembali anyway.
Jadi mengapa tidak hanya menggantikan hujah kita dengan hujah yang dikemaskini dan mula semula?
Jika fungsi tidak rekursi ekor, jika anda melakukan sesuatu seperti -
[Pelajar] jika bar (x + 1). >> Yeah.
>> Jadi, jika anda meletakkan ia dalam keadaan, maka anda melakukan sesuatu dengan nilai pulangan.
Atau walaupun anda hanya melakukan pulangan 2 * bar (x - 1).
Jadi sekarang bar (x - 1) perlu kembali dalam usaha untuk ia mengira 2 kali bahawa nilai,
jadi sekarang ia tidak memerlukan bingkai tindanan sendiri yang berasingan,
dan kini, tidak kira berapa keras anda cuba, anda akan perlu -
Ini bukan ekor rekursi.
[Pelajar] saya cuba untuk membawa rekursi bertujuan untuk rekursi ekor -
[Bowden] Dalam dunia yang ideal, tetapi dalam CS50 anda tidak perlu.
Dalam usaha untuk mendapatkan rekursi ekor, secara amnya, anda menubuhkan hujah tambahan
mana bar akan mengambil int x ke y
dan y sepadan dengan perkara utama yang anda mahu untuk kembali.
Jadi maka ini anda akan kembali bar (x - 1), 2 * y.
Jadi itulah hanya peringkat tinggi bagaimana anda mengubah perkara yang menjadi ekor rekursi.
Tetapi hujah tambahan -
Dan kemudian di akhir apabila anda mencapai kes asas anda, anda hanya kembali y
kerana anda telah mengumpul masa keseluruhan nilai pulangan yang anda mahu.
Anda jenis telah melakukannya iterative tetapi menggunakan panggilan rekursi.
Soalan?
[Pelajar] Mungkin tentang aritmetik penunjuk, seperti apabila menggunakan tali. >> Pasti.
Aritmetik pointer.
Apabila menggunakan tali ia mudah kerana rentetan bintang char,
aksara adalah selama-lamanya dan sentiasa bait tunggal,
dan jadi aritmetik penunjuk adalah bersamaan dengan aritmetik tetap apabila anda berurusan dengan rentetan.
Mari kita hanya mengatakan char * s = "hello".
Jadi kita mempunyai blok dalam ingatan.
Ia memerlukan 6 bait kerana anda sentiasa perlu null.
Dan char * s akan ke titik permulaan array ini.
Jadi s mata di sana.
Sekarang, ini adalah pada dasarnya bagaimana pelbagai apa-apa kerja,
tanpa mengira sama ada ia adalah pulangan oleh malloc atau sama ada ia adalah pada timbunan.
Pelbagai Mana-mana asasnya penunjuk permulaan array,
dan kemudian mana-mana operasi array, pengindeksan mana-mana, hanya pergi ke pelbagai yang tertentu mengimbangi.
>> Jadi, apabila saya mengatakan sesuatu seperti [3]; ini akan s dan mengira 3 aksara.
Jadi s [3], kita mempunyai 0, 1, 2, 3, jadi s [3] akan merujuk kepada l ini.
[Pelajar] Dan kita boleh mencapai nilai yang sama dengan melakukan s + 3 dan kemudian bintang kurungan?
Ya.
Ini adalah bersamaan dengan * (+ 3);
dan itu adalah selama-lamanya dan sentiasa bersamaan tidak kira apa yang kamu lakukan.
Anda tidak perlu untuk menggunakan sintaks kurungan.
Anda sentiasa boleh menggunakan * sintaks (s + 3).
Orang cenderung untuk suka sintaks kurungan, walaupun.
[Pelajar] Jadi semua array sebenarnya hanya petunjuk.
Ada perbezaan sedikit apabila saya mengatakan int x [4]; >> [pelajar] Adakah yang mencipta memori?
[Bowden] Itu akan mewujudkan 4 ints pada timbunan, jadi keseluruhan 16 bait.
Ia akan mewujudkan 16 bait pada timbunan.
x tidak disimpan di mana-mana.
Ia adalah hanya simbol merujuk kepada permulaan perkara itu.
Kerana anda mengisytiharkan array di dalam fungsi ini,
apa pengkompil akan lakukan hanya menggantikan semua kejadian x ubah
dengan mana ia berlaku untuk memilih untuk meletakkan 16 bait.
Ia tidak boleh berbuat demikian dengan char * s kerana s merupakan penunjuk sebenar.
Ia adalah percuma untuk kemudian menunjukkan kepada perkara-perkara lain.
x ialah pemalar. Anda tidak boleh mempunyai ia satu titik untuk pelbagai berbeza. >> [Pelajar] Okay.
Tetapi idea ini, pengindeksan ini, adalah sama tanpa mengira sama ada ia adalah pelbagai tradisional
atau jika ia adalah penunjuk kepada sesuatu atau jika ia penunjuk kepada pelbagai malloced.
Dan pada hakikatnya, ia begitu bersamaan bahawa itu adalah juga perkara yang sama.
Ia sebenarnya hanya diterjemahkan apa yang di dalam kurungan dan apa yang ditinggalkan kurungan,
menambah mereka bersama-sama, dan dereferences.
Jadi ini adalah hanya sebagai sah sebagai * (s + 3) atau s [3].
[Pelajar] Bolehkah anda mempunyai petunjuk menunjuk kepada barisan 2-dimensi?
>> Ia lebih sukar. Secara tradisinya, tidak.
Satu pelbagai 2-dimensi adalah hanya pelbagai 1-dimensi dengan sintaks beberapa mudah
kerana apabila saya mengatakan int x [3] [3], ini adalah benar-benar hanya 1 tatasusunan dengan 9 nilai.
Dan sebagainya apabila saya indeks, pengkompil tahu apa yang saya maksudkan.
Jika saya katakan x [1] [2], ia tahu saya mahu pergi ke barisan kedua, jadi ia akan melangkau 3 pertama,
dan kemudian ia mahu perkara kedua dalam itu, jadi ia akan mendapatkan satu ini.
Tetapi ia masih hanya pelbagai dimensi tunggal.
Dan jadi jika saya mahu memberi penunjuk kepada pelbagai itu,
Saya akan mengatakan int * p = x;
Jenis x hanya -
Ia adalah jenis kasar mengatakan x kerana ia adalah hanya simbol dan ia bukan satu pembolehubah yang sebenar,
tetapi ia hanya * int.
x hanya penunjuk untuk permulaan ini. >> [Pelajar] Okay.
Dan jadi saya tidak akan dapat untuk mengakses [1] [2].
Saya fikir terdapat sintaks khas untuk mengisytiharkan penunjuk,
sesuatu yang tidak masuk akal seperti int (* p [- sesuatu yang benar-benar tidak masuk akal, saya tidak tahu.
Tetapi ada satu sintaks untuk mengisytiharkan petunjuk seperti dengan kurungan dan perkara-perkara.
Ia mungkin tidak membolehkan anda berbuat demikian.
Saya boleh melihat kembali pada sesuatu yang akan beritahu saya kebenaran.
Saya akan mencari kemudian, jika terdapat sintaks untuk titik. Tetapi anda tidak akan melihat ia.
Dan walaupun sintaks begitu kuno bahawa jika anda menggunakan ia, orang akan bingung.
Tatasusunan multidimensi cukup jarang berlaku kerana ia adalah.
Anda cukup banyak -
Nah, jika anda melakukan perkara-perkara matriks ia tidak akan menjadi jarang,
tetapi dalam C anda jarang akan menggunakan tatasusunan multidimensi.
Yeah. >> [Pelajar] Katakan anda mempunyai pelbagai yang benar-benar panjang.
>> Jadi dalam ingatan maya, ia akan muncul untuk menjadi semua berturut-turut,
seperti elemen-elemen yang betul-betul bersebelahan antara satu sama lain,
tetapi dalam memori fizikal, ia akan menjadi mustahil bagi yang akan berpecah? >> Ya.
Bagaimana kerja-kerja maya memori ia hanya memisahkan -
Unit peruntukan adalah halaman, yang cenderung untuk menjadi 4 kilobytes,
dan sebagainya apabila proses berkata, hey, saya mahu untuk menggunakan memori ini,
sistem operasi akan memperuntukkan 4 kilobytes untuk blok yang sedikit memori.
Malah jika anda hanya menggunakan satu bait tunggal sedikit dalam blok keseluruhan ingatan,
sistem operasi akan memberi ia penuh 4 kilobait.
Jadi apakah ini bermakna saya boleh mempunyai - katakan ini adalah timbunan saya.
Timbunan ini boleh dipisahkan. Timbunan saya boleh megabait dan megabait.
Timbunan saya boleh menjadi besar.
Tetapi timbunan itu sendiri akan berpecah ke dalam laman individu,
yang jika kita melihat di sini mari kita mengatakan ini adalah RAM kita,
jika saya mempunyai 2 Gigabyte RAM, ini ialah 0 alamat sebenar seperti bait 0 RAM saya,
dan ini adalah 2 gigabait sepanjang jalan ke sini.
Jadi halaman ini mungkin sesuai untuk blok ini di sini.
Laman ini mungkin sesuai untuk blok ini di sini.
Ini mungkin sesuai kepada yang satu ini di sini.
Jadi sistem operasi adalah bebas untuk memberikan memori fizikal
kepada mana-mana halaman individu secara sewenang-wenangnya.
Dan itu bererti bahawa jika sempadan ini berlaku untuk bercelapak array,
array berlaku untuk kiri dan kanan perintah ini halaman,
maka pelbagai bahawa akan berpecah dalam memori fizikal.
Dan kemudian apabila anda berhenti program ini, apabila proses itu berakhir,
pemetaan ini mendapat terpadam dan kemudian ia adalah bebas untuk menggunakan blok-blok kecil untuk perkara-perkara lain.
Lebih banyak soalan?
[Pelajar] aritmetik penunjuk. >> Oh yeah.
Strings adalah lebih mudah, tetapi melihat sesuatu seperti ints,
kembali ke int x [4];
Sama ada ini adalah array atau sama ada ia adalah penunjuk kepada pelbagai malloced daripada 4 integer,
ia akan dirawat dengan cara yang sama.
[Pelajar] Jadi tatasusunan adalah pada timbunan?
[Bowden] Perlengkapan tidak pada timbunan. >> [Pelajar] Oh.
>> [Bowden] Ini jenis pelbagai cenderung untuk menjadi pada timbunan
melainkan anda mengisytiharkan ia di - mengabaikan pembolehubah global. Jangan gunakan pembolehubah global.
Dalam fungsi saya katakan int x [4];
Ia akan mewujudkan satu blok 4-integer pada timbunan untuk pelbagai ini.
Tetapi ini malloc (4 * sizeof (int)); akan pergi pada timbunan.
Tetapi selepas titik ini saya boleh menggunakan x dan p dalam cukup banyak cara yang sama,
selain pengecualian yang saya katakan sebelum tentang anda boleh menyerahhakkan semula p.
Teknikalnya, saiz mereka adalah agak berbeza, tetapi yang benar-benar tidak relevan.
Anda sebenarnya tidak pernah menggunakan saiz mereka.
P saya boleh katakan p [3] = 2; atau x [3] = 2;
Anda boleh menggunakan mereka dalam cara yang tepat sama.
Jadi aritmetik penunjuk sekarang - Ya.
[Pelajar] Adakah anda tidak perlu melakukan p * jika anda mempunyai kurungan?
Kurungan adalah dereference tersirat. >> Okay.
Sebenarnya, juga apa yang anda katakan dengan anda boleh mendapatkan tatasusunan multidimensi
dengan petunjuk, apa yang boleh anda lakukan adalah sesuatu seperti, katakan, int ** pp = malloc (sizeof (int *) * 5);
Saya hanya akan menulis semua keluar pertama.
Saya tidak mahu bahawa satu.
Okay.
Apa yang saya lakukan di sini adalah - Itu harus pp [i].
Jadi pp adalah penunjuk kepada penunjuk.
Anda sedang mallocing pp untuk menunjukkan pelbagai 5 bintang int.
Jadi dalam ingatan anda mempunyai pada ms tindanan
Ia akan menunjukkan pelbagai 5 blok yang semua sendiri petunjuk.
Dan kemudian apabila saya malloc ke sini, saya malloc bahawa setiap mereka petunjuk individu
harus menunjukkan blok berasingan daripada 4 bait pada timbunan.
Jadi ini mata kepada 4 bait.
Dan ini satu mata kepada 4 bait yang berbeza.
>> Dan kesemua mereka menunjukkan mereka sendiri 4 bait.
Ini memberikan saya satu cara untuk melakukan perkara-perkara yang multidimensi.
Saya boleh mengatakan pp [3] [4], tetapi sekarang ini tidak adalah perkara yang sama sebagai tatasusunan multidimensi
kerana tatasusunan multidimensi ia diterjemahkan [3] [4] ke dalam satu diimbangi ke dalam tatasusunan x.
Ini p dereferences, mengakses indeks ketiga, maka dereferences yang
dan mengakses - 4 akan menjadi sah - indeks kedua.
Manakala apabila kita mempunyai int x [3] [4] sebelum sebagai pelbagai multidimensi
dan apabila anda menggandakan kurungan ia adalah benar-benar hanya dereference tunggal,
anda sedang mengikuti penunjuk tunggal dan kemudian satu ofset,
ini adalah benar-benar rujukan 2D.
Anda mengikuti 2 petunjuk yang berasingan.
Jadi ini juga teknikal membolehkan anda untuk mempunyai tatasusunan multidimensi
di mana setiap individu pelbagai saiz yang berbeza.
Jadi saya fikir bergerigi tatasusunan multidimensi adalah apa ia dipanggil
kerana benar-benar perkara pertama yang boleh menunjukkan kepada sesuatu yang mempunyai 10 unsur,
Perkara kedua yang boleh menunjukkan kepada sesuatu yang mempunyai 100 unsur.
[Pelajar] Adakah terdapat apa-apa had kepada bilangan penunjuk anda boleh mempunyai
menunjuk kepada petunjuk lain? >> No.
Anda boleh mempunyai int ***** p.
Kembali kepada aritmetik penunjuk - >> [pelajar] Oh. >> Yeah.
[Pelajar] Jika saya mempunyai int *** p dan kemudian saya melakukan dereferencing satu dan saya katakan p * adalah bersamaan dengan nilai ini,
ia hanya akan untuk melakukan tahap 1 dereferencing? >> Ya.
Jadi jika saya mahu mengakses perkara yang penunjuk terakhir menunjuk pada -
Kemudian anda melakukan p ***. >> Okay.
Jadi ini adalah mata p 1 blok, mata ke blok lain, mata ke blok lain.
Kemudian jika anda lakukan * p = sesuatu yang lain, maka anda akan berubah ini
kini menunjukkan ke blok berbeza. >> Okay.
>> [Bowden] Dan jika ini telah malloced, maka anda kini telah bocor memori
melainkan jika anda mempunyai rujukan yang berbeza ini
kerana anda tidak boleh mendapatkan kembali kepada orang-orang yang bahawa anda hanya melemparkan.
Aritmetik pointer.
int x [4]; akan memperuntukkan pelbagai daripada 4 integer
mana x akan ke titik permulaan array.
Jadi, apabila saya berkata sesuatu seperti x [1]; saya mahu ia bermakna pergi ke integer kedua dalam array,
yang akan menjadi salah satu ini.
Tetapi benar-benar, itulah 4 bait ke dalam array sejak integer ini mengambil masa sehingga 4 bait.
Jadi mengimbangi 1 benar-benar bermakna mengimbangi 1
kali saiz apa jua jenis array.
Ini adalah pelbagai integer, jadi ia tahu untuk berbuat 1 kali saiz int apabila ia mahu untuk mengimbangi.
Sintaks lain. Ingatlah bahawa ini adalah bersamaan dengan * (x + 1);
Bila saya katakan penunjuk + 1, apa yang pulangan adalah alamat bahawa penunjuk menyimpan
ditambah 1 kali saiz jenis penunjuk.
Jadi, jika x = ox100, maka x + 1 = ox104.
Dan anda boleh menyalahgunakan ini dan mengatakan sesuatu seperti char * c = (char *) x;
dan kini c akan menjadi alamat yang sama seperti x.
c akan menjadi sama dengan ox100,
tetapi c + 1 akan menjadi sama dengan ox101
sejak aritmetik penunjuk bergantung kepada jenis penunjuk bahawa anda menambah.
Jadi c + 1, ia kelihatan di c, ia adalah penunjuk char, jadi ia akan untuk menambah 1 kali saiz char,
yang sentiasa akan menjadi 1, jadi anda mendapat 101,
sedangkan jika saya melakukan x, yang juga masih 100, x + 1 akan menjadi 104.
[Pelajar] Bolehkah anda menggunakan c + + dalam usaha untuk memajukan pointer anda dengan 1?
Ya, anda boleh.
Anda tidak boleh berbuat demikian dengan x kerana x adalah hanya simbol, ia adalah pemalar; anda tidak boleh menukar x.
>> Tetapi c berlaku hanya menjadi penunjuk, jadi c + + adalah sah dan ia akan kenaikan sebanyak 1.
Jika c hanya * int, maka c + + akan 104.
+ + Tidak penunjuk aritmetik seperti c + 1 akan mempunyai dilakukan penunjuk aritmetik.
Ini sebenarnya adalah bagaimana banyak perkara seperti apapun merge -
Sebaliknya mewujudkan salinan perkara, sebaliknya anda boleh lulus -
Seperti jika saya mahu lulus separuh array - biarkan yang memadam beberapa ini.
Katakan saya mahu lulus sampingan ini array ke dalam fungsi.
Apa yang saya akan lulus dengan fungsi itu?
Jika saya lulus x, saya lulus alamat ini.
Tetapi saya mahu lulus alamat tertentu. Jadi apa yang saya perlu lulus?
[Pelajar] pointer + 2?
[Bowden] Jadi x + 2. Ya.
Itu akan menjadi alamat ini.
Anda akan juga sangat kerap melihat ia sebagai x [2] dan kemudian alamat itu.
Jadi, anda perlu mengambil alamat kerana kurungan adalah dereference tersirat.
x [2] merujuk kepada nilai yang berada dalam kotak ini, dan kemudian anda mahu alamat kotak yang,
jadi anda mengatakan & x [2].
Jadi itulah bagaimana sesuatu apapun merge di mana anda mahu untuk lulus setengah senarai kepada sesuatu
anda benar-benar hanya lulus & x [2], dan kini sejauh panggilan rekursi berkenaan,
pelbagai baru saya bermula di sana.
Soalan minit terakhir.
[Pelajar] Jika kita tidak meletakkan #: glib satu atau - apa yang dipanggil? >> Bintang?
[Pelajar] Bintang. Teknikalnya >>, dereference pengendali, tetapi - >> [pelajar] Dereference.
>> Jika kita tidak meletakkan bintang atau #: glib, apa yang berlaku jika saya hanya mengatakan y = x dan x adalah penunjuk?
Apakah jenis y? >> [Pelajar] saya hanya akan mengatakan penunjuk ia 2.
Jadi jika anda hanya mengatakan y = x, sekarang x dan y titik kepada perkara yang sama. >> [Pelajar] Point kepada perkara yang sama.
Dan jika x ialah penunjuk int? >> Ia akan mengadu kerana anda tidak boleh menyerahhakkan petunjuk.
[Pelajar] Okay.
Ingatlah bahawa petunjuk, walaupun kita menarik mereka sebagai anak panah,
benar-benar semua kedai mereka - int * x - benar-benar semua x menyimpan sesuatu seperti ox100,
mana kita berlaku untuk mewakili sebagai menunjuk ke blok disimpan di 100.
Jadi, apabila saya mengatakan int * y = x; saya hanya menyalin ox100 ke y,
yang kita hanya akan untuk mewakili sebagai y, juga menunjuk ke ox100.
Dan jika saya katakan int i = (int) x; maka i akan menyimpan apa jua nilai ox100
di dalamnya, tetapi kini ia akan ditafsirkan sebagai integer bukan penunjuk.
Tetapi anda perlu dibuang atau jika tidak, ia akan mengadu.
[Pelajar] Jadi adakah anda bermakna untuk membuang -
Adakah ia akan pemutus int x atau pemutus int y?
[Bowden] Apa?
[Pelajar] Okay. Selepas kurungan ini ada akan menjadi x atau ay sana?
>> [Bowden] Sama ada. x dan y adalah sama. >> [Pelajar] Okay.
Kerana mereka berdua petunjuk. >> Yeah.
[Pelajar] Maka ia akan menyimpan 100 perenambelasan dalam bentuk integer? >> [Bowden] Yeah.
Tetapi tidak nilai apa sahaja yang ia menunjuk ke.
[Bowden] Yeah. >> [Pelajar] Jadi hanya alamat dalam bentuk integer. Okay.
[Bowden] Jika anda mahu untuk sebab-sebab tertentu yang pelik,
anda boleh berurusan eksklusif dengan petunjuk dan tidak pernah berurusan dengan integer
dan hanya menjadi seperti int * x = 0.
Kemudian anda akan mendapat benar-benar keliru apabila aritmetik penunjuk bermula berlaku.
Jadi nombor yang mereka menyimpan adalah sia-sia.
Ia hanya bagaimana anda akhirnya mentafsirkan mereka.
Jadi saya bebas untuk menyalin ox100 dari * int int an,
dan saya bebas untuk menetapkan - you're mungkin akan mendapatkan menjerit kerana tidak pemutus -
Saya bebas untuk memberikan sesuatu seperti (int *) ox1234 ke * int ini sewenang-wenangnya.
Jadi ox123 adalah hanya sebagai sah alamat memori & y.
& Y berlaku untuk mengembalikan sesuatu yang cukup banyak ox123.
[Pelajar] yang Adakah cara yang benar-benar sejuk untuk pergi dari perenambelasan kepada bentuk perpuluhan,
suka jika anda mempunyai penunjuk dan anda membuang ia sebagai int an?
[Bowden] Anda benar-benar hanya boleh mencetak menggunakan seperti printf.
Katakan saya mempunyai int y = 100.
Jadi printf (% d \ n - kerana anda sudah perlu tahu - mencetak bahawa sebagai integer% x,.
Kami hanya akan mencetak ia sebagai perenambelasan.
Jadi penunjuk tidak disimpan sebagai perenambelasan,
dan integer tidak disimpan sebagai perpuluhan.
Semuanya disimpan sebagai binari.
Ia hanya bahawa kita cenderung untuk menunjukkan penunjuk sebagai perenambelasan
kerana kita berfikir tentang perkara-perkara dalam blok-blok 4-bait,
dan alamat memori cenderung untuk menjadi biasa.
Kami seperti, jika ia bermula dengan bf, maka ia berlaku pada timbunan.
Jadi ia hanya tafsiran kita petunjuk sebagai perenambelasan.
Okay. Sebarang soalan terakhir?
>> Saya akan berada di sini untuk sedikit selepas jika anda mempunyai apa-apa lagi.
Dan itulah akhir itu.
>> [Pelajar] Yay! [Tepukan]
>> [CS50.TV]