1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Bagian 4 - Lebih Nyaman] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvard University] 3 00:00:04,850 --> 00:00:07,370 [Ini adalah CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Kami memiliki besok kuis, dalam kasus kalian tidak tahu itu. 5 00:00:14,810 --> 00:00:20,970 Hal ini pada dasarnya pada semua yang anda bisa melihat di kelas atau seharusnya melihat di kelas. 6 00:00:20,970 --> 00:00:26,360 Itu termasuk pointer, meskipun mereka topik yang sangat baru-baru ini. 7 00:00:26,360 --> 00:00:29,860 Anda setidaknya harus memahami tingkat tinggi dari mereka. 8 00:00:29,860 --> 00:00:34,760 Apa pun yang pergi lebih di kelas Anda harus memahami untuk kuis. 9 00:00:34,760 --> 00:00:37,320 Jadi jika Anda memiliki pertanyaan pada mereka, Anda dapat meminta mereka sekarang. 10 00:00:37,320 --> 00:00:43,280 Tapi ini akan menjadi sesi yang sangat dipimpin mahasiswa di mana kalian mengajukan pertanyaan, 11 00:00:43,280 --> 00:00:45,060 jadi mudah-mudahan orang memiliki pertanyaan. 12 00:00:45,060 --> 00:00:48,020 Apakah ada yang punya pertanyaan? 13 00:00:49,770 --> 00:00:52,090 Ya. >> [Mahasiswa] Dapatkah Anda pergi ke pointer lagi? 14 00:00:52,090 --> 00:00:54,350 Aku akan pergi ke pointer. 15 00:00:54,350 --> 00:00:59,180 Semua variabel Anda selalu hidup dalam memori, 16 00:00:59,180 --> 00:01:04,450 tetapi biasanya Anda tidak perlu khawatir tentang itu dan Anda hanya mengatakan x + 2 dan y + 3 17 00:01:04,450 --> 00:01:07,080 dan compiler akan mencari tahu di mana hal-hal yang hidup untuk Anda. 18 00:01:07,080 --> 00:01:12,990 Setelah Anda sedang berhadapan dengan pointer, sekarang kau eksplisit menggunakan alamat tersebut memori. 19 00:01:12,990 --> 00:01:19,800 Jadi variabel tunggal hanya akan pernah tinggal di satu alamat pada waktu tertentu. 20 00:01:19,800 --> 00:01:24,040 Jika kita ingin mendeklarasikan pointer, apa jenis akan terlihat seperti? 21 00:01:24,040 --> 00:01:26,210 >> Saya ingin menyatakan p pointer. Apa jenis terlihat seperti? 22 00:01:26,210 --> 00:01:33,530 [Mahasiswa] int * p. >> Ya. Jadi int * p. 23 00:01:33,530 --> 00:01:38,030 Dan bagaimana cara membuatnya menunjuk ke x? >> [Mahasiswa] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Jadi ampersand secara harfiah disebut alamat operator. 25 00:01:45,300 --> 00:01:50,460 Jadi ketika saya mengatakan & x itu mendapatkan alamat memori dari variabel x. 26 00:01:50,460 --> 00:01:56,790 Jadi sekarang aku punya p pointer, dan di mana saja di kode saya, saya dapat menggunakan p * 27 00:01:56,790 --> 00:02:02,960 atau saya bisa menggunakan x dan itu akan menjadi hal yang sama persis. 28 00:02:02,960 --> 00:02:09,520 (* P). Apa ini lakukan? Apa Bintang artinya? 29 00:02:09,520 --> 00:02:13,120 [Mahasiswa] Ini berarti nilai pada saat itu. >> Ya. 30 00:02:13,120 --> 00:02:17,590 Jadi jika kita melihatnya, itu bisa sangat berguna untuk menarik keluar diagram 31 00:02:17,590 --> 00:02:22,230 di mana ini adalah sebuah kotak kecil dari memori untuk x, yang kebetulan memiliki nilai 4, 32 00:02:22,230 --> 00:02:25,980 maka kita memiliki sebuah kotak kecil dari memori untuk p, 33 00:02:25,980 --> 00:02:31,590 dan sebagainya poin p ke x, jadi kita menarik panah dari p ke x. 34 00:02:31,590 --> 00:02:40,270 Jadi ketika kita mengatakan * p kita katakan pergi ke kotak yang p. 35 00:02:40,270 --> 00:02:46,480 Star adalah mengikuti panah dan kemudian melakukan apa pun yang Anda inginkan dengan kotak yang di sana. 36 00:02:46,480 --> 00:03:01,090 Jadi bisa saya katakan * p = 7, dan yang akan masuk ke kotak yang x dan perubahan yang ke 7. 37 00:03:01,090 --> 00:03:13,540 Atau aku bisa mengatakan int z = * p * 2; Itu membingungkan karena bintang itu, bintang. 38 00:03:13,540 --> 00:03:19,230 Bintang satu dereferencing p, bintang lain mengalikan dengan 2. 39 00:03:19,230 --> 00:03:26,780 Perhatikan Aku bisa saja juga menggantikan p * dengan x. 40 00:03:26,780 --> 00:03:29,430 Anda dapat menggunakannya dengan cara yang sama. 41 00:03:29,430 --> 00:03:38,000 Dan kemudian nanti saya bisa memiliki titik p ke hal yang sama sekali baru. 42 00:03:38,000 --> 00:03:42,190 Saya hanya dapat mengatakan p = &z; 43 00:03:42,190 --> 00:03:44,940 Jadi sekarang p ada poin lagi untuk x; menunjuk ke z. 44 00:03:44,940 --> 00:03:50,510 Dan setiap kali saya melakukan p * itu sama dengan melakukan z. 45 00:03:50,510 --> 00:03:56,170 Jadi hal yang berguna tentang ini adalah sekali kita mulai masuk ke fungsi. 46 00:03:56,170 --> 00:03:59,790 >> Ini semacam berguna untuk menyatakan pointer yang menunjuk ke sesuatu 47 00:03:59,790 --> 00:04:03,140 dan kemudian Anda hanya dereferencing itu 48 00:04:03,140 --> 00:04:06,060 ketika Anda bisa menggunakan variabel asli untuk memulai. 49 00:04:06,060 --> 00:04:18,190 Tapi ketika Anda masuk ke fungsi - jadi mari kita mengatakan bahwa kita memiliki beberapa fungsi, int foo, 50 00:04:18,190 --> 00:04:32,810 yang mengambil pointer dan hanya melakukan * p = 6; 51 00:04:32,810 --> 00:04:39,990 Seperti yang kita lihat sebelumnya dengan swap, Anda tidak dapat melakukan swap yang efektif dan fungsi yang terpisah 52 00:04:39,990 --> 00:04:45,180 dengan hanya melewati bilangan bulat karena segala sesuatu di C selalu lewat nilai. 53 00:04:45,180 --> 00:04:48,360 Bahkan ketika Anda melewati pointer Anda sedang lewat nilai. 54 00:04:48,360 --> 00:04:51,940 Kebetulan bahwa nilai-nilai adalah alamat memori. 55 00:04:51,940 --> 00:05:00,770 Jadi ketika saya mengatakan foo (p), saya sedang melewati pointer ke fungsi foo 56 00:05:00,770 --> 00:05:03,910 dan kemudian melakukan foo * p = 6; 57 00:05:03,910 --> 00:05:08,600 Jadi dalam fungsi itu, * p masih setara dengan x, 58 00:05:08,600 --> 00:05:12,720 tapi saya tidak dapat menggunakan x dalam fungsi yang karena itu tidak scoped dalam fungsi itu. 59 00:05:12,720 --> 00:05:19,510 Jadi * p = 6 adalah satu-satunya cara saya dapat mengakses variabel lokal dari fungsi lain. 60 00:05:19,510 --> 00:05:23,600 Atau, juga, pointer adalah satu-satunya cara saya dapat mengakses variabel lokal dari fungsi lain. 61 00:05:23,600 --> 00:05:31,600 [Mahasiswa] Mari mengatakan Anda ingin kembali pointer. Bagaimana tepatnya Anda melakukannya? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Kembali pointer seperti dalam sesuatu seperti int y = 3, kembali & y? >> [Mahasiswa] Ya. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Oke. Anda tidak harus melakukan ini. Ini buruk. 64 00:05:48,480 --> 00:05:59,480 Saya pikir saya melihat dalam slide kuliah Anda mulai melihat ini diagram seluruh memori 65 00:05:59,480 --> 00:06:02,880 di mana di sini Anda punya alamat memori 0 66 00:06:02,880 --> 00:06:09,550 dan di sini Anda memiliki alamat memori 4 gigs atau 2 ke 32. 67 00:06:09,550 --> 00:06:15,120 Jadi Anda punya beberapa hal dan beberapa barang dan kemudian Anda memiliki tumpukan Anda 68 00:06:15,120 --> 00:06:21,780 dan Anda punya tumpukan Anda, yang Anda baru saja mulai belajar tentang, tumbuh dewasa. 69 00:06:21,780 --> 00:06:24,390 [Mahasiswa] Bukankah tumpukan di atas tumpukan? 70 00:06:24,390 --> 00:06:27,760 >> Ya. Tumpukan adalah di atas, bukan? >> [Mahasiswa] Yah, ia meletakkan 0 di atas. 71 00:06:27,760 --> 00:06:30,320 [Mahasiswa] Oh, ia meletakkan 0 di atas. >> [Mahasiswa] Oh, oke. 72 00:06:30,320 --> 00:06:36,060 Disclaimer: Di mana saja dengan CS50 Anda akan melihatnya dengan cara ini. >> [Mahasiswa] Oke. 73 00:06:36,060 --> 00:06:40,290 Hanya saja ketika Anda pertama kali melihat tumpukan, 74 00:06:40,290 --> 00:06:45,000 seperti ketika Anda memikirkan tumpukan Anda memikirkan hal-hal yang menumpuk di atas satu sama lain. 75 00:06:45,000 --> 00:06:50,810 Jadi kita cenderung untuk flip ini sekitar sehingga tumpukan tersebut tumbuh seperti stack biasanya akan 76 00:06:50,810 --> 00:06:55,940 bukannya stack tergantung ke bawah. >> [Mahasiswa] Jangan tumpukan teknis tumbuh juga, meskipun? 77 00:06:55,940 --> 00:07:01,100 Itu tergantung pada apa yang Anda maksud dengan tumbuh. 78 00:07:01,100 --> 00:07:04,010 Tumpukan dan tumpukan selalu tumbuh dalam arah yang berlawanan. 79 00:07:04,010 --> 00:07:09,420 Sebuah tumpukan selalu tumbuh dalam arti bahwa itu tumbuh 80 00:07:09,420 --> 00:07:12,940 menuju alamat memori yang lebih tinggi, dan tumpukan tumbuh ke bawah 81 00:07:12,940 --> 00:07:17,260 di bahwa itu berkembang menuju alamat memori yang lebih rendah. 82 00:07:17,260 --> 00:07:20,250 Jadi atas adalah 0 dan bagian bawah adalah alamat memori tinggi. 83 00:07:20,250 --> 00:07:26,390 Mereka berdua tumbuh, hanya dalam menentang arah. 84 00:07:26,390 --> 00:07:29,230 [Mahasiswa] Saya hanya berarti bahwa karena Anda mengatakan Anda menaruh tumpukan di bagian bawah 85 00:07:29,230 --> 00:07:33,640 karena tampaknya lebih intuitif karena untuk stack untuk memulai di bagian atas tumpukan, 86 00:07:33,640 --> 00:07:37,520 tumpukan yang ada di atas dirinya sendiri juga, jadi ltu - >> Ya. 87 00:07:37,520 --> 00:07:44,960 Anda juga memikirkan tumpukan sebagai orang yang tumbuh dan besar, tetapi tumpukan lebih. 88 00:07:44,960 --> 00:07:50,280 Jadi tumpukan adalah salah satu yang kami jenis ingin menunjukkan tumbuh dewasa. 89 00:07:50,280 --> 00:07:55,390 Tapi di mana-mana Anda melihat sebaliknya akan menampilkan alamat 0 di bagian atas 90 00:07:55,390 --> 00:07:59,590 dan alamat memori tertinggi di bagian bawah, jadi ini adalah pandangan yang biasa Anda memori. 91 00:07:59,590 --> 00:08:02,100 >> Apakah Anda memiliki pertanyaan? 92 00:08:02,100 --> 00:08:04,270 [Mahasiswa] Bisakah Anda ceritakan lebih lanjut tentang tumpukan? 93 00:08:04,270 --> 00:08:06,180 Ya. Aku akan mendapatkan bahwa dalam satu detik. 94 00:08:06,180 --> 00:08:12,220 Pertama, akan kembali ke mengapa kembali & y adalah hal yang buruk, 95 00:08:12,220 --> 00:08:18,470 di stack Anda memiliki banyak frame stack yang mewakili semua fungsi 96 00:08:18,470 --> 00:08:20,460 yang telah dipanggil. 97 00:08:20,460 --> 00:08:27,990 Jadi mengabaikan hal-hal sebelumnya, bagian atas tumpukan Anda selalu akan menjadi fungsi utama 98 00:08:27,990 --> 00:08:33,090 karena itulah fungsi pertama yang dipanggil. 99 00:08:33,090 --> 00:08:37,130 Dan kemudian ketika Anda memanggil fungsi lain, stack akan tumbuh ke bawah. 100 00:08:37,130 --> 00:08:41,640 Jadi jika saya memanggil beberapa fungsi, foo, dan itu akan stack frame sendiri, 101 00:08:41,640 --> 00:08:47,280 dapat memanggil beberapa fungsi, bar, mendapat tumpukan bingkai sendiri. 102 00:08:47,280 --> 00:08:49,840 Dan bar bisa rekursif dan bisa menyebut dirinya, 103 00:08:49,840 --> 00:08:54,150 dan agar panggilan kedua ke bar akan mendapatkan tumpukan bingkai sendiri. 104 00:08:54,150 --> 00:08:58,880 Dan jadi apa yang terjadi dalam frame stack semua variabel lokal 105 00:08:58,880 --> 00:09:03,450 dan semua argumen fungsi yang - 106 00:09:03,450 --> 00:09:08,730 Setiap hal yang lokal scoped untuk fungsi ini masuk dalam stack frame. 107 00:09:08,730 --> 00:09:21,520 Jadi itu berarti ketika saya mengatakan sesuatu seperti bar adalah fungsi, 108 00:09:21,520 --> 00:09:29,270 Aku hanya akan mendeklarasikan integer dan kemudian kembali pointer ke integer yang. 109 00:09:29,270 --> 00:09:33,790 Jadi bagaimana y tinggal? 110 00:09:33,790 --> 00:09:36,900 [Mahasiswa] y tinggal di bar. >> [Bowden] Ya. 111 00:09:36,900 --> 00:09:45,010 Di suatu tempat di alun-alun kecil memori adalah persegi littler yang memiliki y di dalamnya. 112 00:09:45,010 --> 00:09:53,370 Ketika aku kembali & y, aku kembali pointer ke blok ini sedikit memori. 113 00:09:53,370 --> 00:09:58,400 Tapi kemudian ketika kembali fungsi, stack frame yang akan muncul dari tumpukan. 114 00:10:01,050 --> 00:10:03,530 Dan itulah mengapa itu disebut stack. 115 00:10:03,530 --> 00:10:06,570 Ini seperti struktur data stack, jika Anda tahu apa itu. 116 00:10:06,570 --> 00:10:11,580 Atau bahkan seperti tumpukan nampan selalu contoh, 117 00:10:11,580 --> 00:10:16,060 utama akan pergi di bagian bawah, maka fungsi pertama Anda menelepon akan pergi di atas itu, 118 00:10:16,060 --> 00:10:20,400 dan Anda tidak bisa kembali ke utama sampai Anda kembali dari semua fungsi yang telah disebut 119 00:10:20,400 --> 00:10:22,340 yang telah ditempatkan di atasnya. 120 00:10:22,340 --> 00:10:28,650 >> [Mahasiswa] Jadi, jika Anda tidak melakukan kembali & y, nilai yang dapat berubah tanpa pemberitahuan. 121 00:10:28,650 --> 00:10:31,290 Ya, ini kan - >> [mahasiswa] Ini bisa ditimpa. >> Ya. 122 00:10:31,290 --> 00:10:34,660 Ini benar-benar - Jika Anda mencoba dan - 123 00:10:34,660 --> 00:10:38,040 Ini juga akan menjadi bar * int karena itu kembali pointer, 124 00:10:38,040 --> 00:10:41,310 sehingga tipe kembali adalah * int. 125 00:10:41,310 --> 00:10:46,500 Jika Anda mencoba untuk menggunakan nilai kembali dari fungsi ini, itu perilaku undefined 126 00:10:46,500 --> 00:10:51,770 karena pointer yang menunjuk ke memori yang buruk. >> [Mahasiswa] Oke. 127 00:10:51,770 --> 00:11:01,250 Jadi bagaimana jika, misalnya, Anda menyatakan int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Itu lebih baik. Ya. 129 00:11:03,740 --> 00:11:07,730 [Mahasiswa] Kami berbicara tentang bagaimana ketika kita tarik hal yang dapat kami recycle bin 130 00:11:07,730 --> 00:11:11,750 mereka tidak benar-benar terhapus, kami hanya kehilangan pointer mereka. 131 00:11:11,750 --> 00:11:15,550 Jadi dalam hal ini kita benar-benar menghapus nilai atau apakah masih ada di memori? 132 00:11:15,550 --> 00:11:19,130 Untuk sebagian besar, itu akan tetap berada di sana. 133 00:11:19,130 --> 00:11:24,220 Tapi katakanlah kita terjadi untuk memanggil beberapa fungsi lainnya, baz. 134 00:11:24,220 --> 00:11:28,990 Baz akan mendapatkan stack frame sendiri di sini. 135 00:11:28,990 --> 00:11:31,470 Ini akan menimpa semua hal ini, 136 00:11:31,470 --> 00:11:34,180 dan kemudian jika Anda kemudian mencoba dan menggunakan pointer yang Anda punya sebelumnya, 137 00:11:34,180 --> 00:11:35,570 itu tidak akan menjadi nilai yang sama. 138 00:11:35,570 --> 00:11:38,150 Ini akan berubah hanya karena Anda disebut baz fungsi. 139 00:11:38,150 --> 00:11:43,080 [Mahasiswa] Tapi kita tidak, akan kita masih mendapatkan 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Dalam semua kemungkinan, Anda akan. 141 00:11:44,990 --> 00:11:49,670 Tapi Anda tidak bisa mengandalkan itu. C hanya mengatakan perilaku undefined. 142 00:11:49,670 --> 00:11:51,920 >> [Mahasiswa] Oh, itu tidak. Oke. 143 00:11:51,920 --> 00:11:58,190 Jadi, ketika Anda ingin kembali pointer, ini adalah di mana malloc datang digunakan. 144 00:12:00,930 --> 00:12:15,960 Saya sedang menulis sebenarnya hanya kembali malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Kami akan pergi ke malloc lebih dalam satu detik, tetapi gagasan malloc adalah semua variabel lokal Anda 146 00:12:24,050 --> 00:12:26,760 selalu pergi di stack. 147 00:12:26,760 --> 00:12:31,570 Apa pun yang terjadi malloced di heap, dan akan selamanya dan selalu berada di heap 148 00:12:31,570 --> 00:12:34,490 sampai Anda secara eksplisit membebaskannya. 149 00:12:34,490 --> 00:12:42,130 Jadi ini berarti bahwa ketika Anda malloc sesuatu, itu akan bertahan hidup setelah kembali fungsi. 150 00:12:42,130 --> 00:12:46,800 [Mahasiswa] Apakah itu bertahan hidup setelah program berhenti berjalan? >> No 151 00:12:46,800 --> 00:12:53,180 Oke, jadi itu akan berada di sana sampai program adalah semua cara dilakukan berjalan. >> Ya. 152 00:12:53,180 --> 00:12:57,510 Kita bisa pergi ke rincian tentang apa yang terjadi ketika program berhenti berjalan. 153 00:12:57,510 --> 00:13:02,150 Anda mungkin perlu untuk mengingatkan saya, tapi itu adalah hal yang terpisah sama sekali. 154 00:13:02,150 --> 00:13:04,190 [Mahasiswa] Jadi malloc menciptakan pointer? >> Ya. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [mahasiswa] saya pikir malloc menunjuk blok memori yang pointer dapat digunakan. 156 00:13:15,400 --> 00:13:19,610 [Bowden] saya ingin diagram itu lagi. >> [Mahasiswa] Jadi fungsi ini bekerja, meskipun? 157 00:13:19,610 --> 00:13:26,430 [Mahasiswa] Ya, malloc menunjuk blok memori yang dapat Anda gunakan, 158 00:13:26,430 --> 00:13:30,470 dan kemudian mengembalikan alamat dari blok pertama dari memori itu. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Ya. Jadi, ketika Anda malloc, Anda meraih beberapa blok memori 160 00:13:36,750 --> 00:13:38,260 yang saat ini di heap. 161 00:13:38,260 --> 00:13:43,040 Jika tumpukan terlalu kecil, maka tumpukan hanya akan tumbuh, dan tumbuh ke arah ini. 162 00:13:43,040 --> 00:13:44,650 Jadi katakanlah tumpukan terlalu kecil. 163 00:13:44,650 --> 00:13:49,960 Maka itu akan tumbuh sedikit dan kembali pointer ke blok ini yang hanya tumbuh. 164 00:13:49,960 --> 00:13:55,130 Ketika Anda barang gratis, Anda membuat lebih banyak ruang di tumpukan, 165 00:13:55,130 --> 00:14:00,030 sehingga kemudian kemudian menelepon untuk malloc dapat menggunakan kembali bahwa memori yang sebelumnya dibebaskan. 166 00:14:00,030 --> 00:14:09,950 Hal penting tentang malloc dan bebas adalah bahwa hal itu memberi Anda kontrol penuh 167 00:14:09,950 --> 00:14:12,700 selama masa blok-blok memori. 168 00:14:12,700 --> 00:14:15,420 Variabel global selalu hidup. 169 00:14:15,420 --> 00:14:18,500 Variabel lokal yang hidup dalam lingkup mereka. 170 00:14:18,500 --> 00:14:22,140 Segera setelah Anda melewati penjepit keriting, variabel lokal yang mati. 171 00:14:22,140 --> 00:14:28,890 Memori Malloced masih hidup ketika Anda ingin menjadi hidup 172 00:14:28,890 --> 00:14:33,480 dan kemudian dilepaskan ketika Anda kirim akan dirilis. 173 00:14:33,480 --> 00:14:38,420 Mereka sebenarnya hanya 3 jenis memori, benar-benar. 174 00:14:38,420 --> 00:14:41,840 Ada manajemen memori otomatis, yang merupakan stack. 175 00:14:41,840 --> 00:14:43,840 Hal-hal terjadi untuk Anda secara otomatis. 176 00:14:43,840 --> 00:14:46,910 Ketika Anda mengatakan int x, memori dialokasikan untuk x int. 177 00:14:46,910 --> 00:14:51,630 Ketika x keluar dari ruang lingkup, memori direklamasi untuk x. 178 00:14:51,630 --> 00:14:54,790 Kemudian ada memori manajemen yang dinamis, yang adalah apa yang malloc, 179 00:14:54,790 --> 00:14:56,740 yang adalah ketika Anda memiliki kontrol. 180 00:14:56,740 --> 00:15:01,290 Anda dinamis memutuskan kapan memori harus dan tidak harus dialokasikan. 181 00:15:01,290 --> 00:15:05,050 Dan kemudian ada statis, yang hanya berarti bahwa ia hidup selamanya, 182 00:15:05,050 --> 00:15:06,610 yang adalah apa variabel global. 183 00:15:06,610 --> 00:15:10,240 Mereka hanya selalu dalam memori. 184 00:15:10,960 --> 00:15:12,760 >> Pertanyaan? 185 00:15:14,490 --> 00:15:17,230 [Mahasiswa] Dapatkah Anda mendefinisikan blok hanya dengan menggunakan kurung kurawal 186 00:15:17,230 --> 00:15:21,220 tetapi tidak harus memiliki jika pernyataan atau pernyataan sementara atau sesuatu seperti itu? 187 00:15:21,220 --> 00:15:29,130 Anda dapat mendefinisikan blok seperti dalam fungsi, namun yang memiliki kurung kurawal juga. 188 00:15:29,130 --> 00:15:32,100 [Mahasiswa] Jadi Anda tidak bisa hanya memiliki seperti sepasang acak kurung kurawal dalam kode Anda 189 00:15:32,100 --> 00:15:35,680 yang memiliki variabel lokal? >> Ya, Anda bisa. 190 00:15:35,680 --> 00:15:45,900 Di dalam bar int kita bisa memiliki {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Itu seharusnya di sini. 192 00:15:48,440 --> 00:15:52,450 Tapi itu benar-benar mendefinisikan lingkup int y. 193 00:15:52,450 --> 00:15:57,320 Setelah itu tanda kurung kurawal kedua, y tidak dapat digunakan lagi. 194 00:15:57,910 --> 00:16:00,630 Anda hampir tidak pernah melakukan hal itu, sekalipun. 195 00:16:02,940 --> 00:16:07,370 Mendapatkan kembali ke apa yang terjadi ketika sebuah program berakhir, 196 00:16:07,370 --> 00:16:18,760 ada semacam kebohongan kesalahpahaman / setengah yang kita berikan untuk hanya membuat segalanya lebih mudah. 197 00:16:18,760 --> 00:16:24,410 Kami memberitahu Anda bahwa ketika Anda mengalokasikan memori 198 00:16:24,410 --> 00:16:29,860 Anda mengalokasikan beberapa potongan RAM untuk variabel tersebut. 199 00:16:29,860 --> 00:16:34,190 Tapi kau tidak benar-benar langsung menyentuh RAM pernah di program Anda. 200 00:16:34,190 --> 00:16:37,490 Jika Anda berpikir tentang itu, bagaimana saya menggambar - 201 00:16:37,490 --> 00:16:44,330 Dan sebenarnya, jika Anda pergi melalui dalam GDB Anda akan melihat hal yang sama. 202 00:16:51,120 --> 00:16:57,590 Terlepas dari berapa kali Anda menjalankan program atau program apa yang Anda jalankan, 203 00:16:57,590 --> 00:16:59,950 stack selalu akan mulai - 204 00:16:59,950 --> 00:17:06,510 Anda selalu akan melihat variabel sekitar sesuatu alamat oxbffff. 205 00:17:06,510 --> 00:17:09,470 Ini biasanya di suatu tempat di wilayah itu. 206 00:17:09,470 --> 00:17:18,760 Tapi bagaimana bisa 2 program mungkin memiliki pointer ke memori yang sama? 207 00:17:20,640 --> 00:17:27,650 [Mahasiswa] Ada beberapa penunjukan sewenang-wenang di mana oxbfff seharusnya pada RAM 208 00:17:27,650 --> 00:17:31,320 yang benar-benar bisa berada di tempat yang berbeda tergantung pada ketika fungsi dipanggil. 209 00:17:31,320 --> 00:17:35,920 Ya. Istilah adalah virtual memory. 210 00:17:35,920 --> 00:17:42,250 Idenya adalah bahwa setiap proses tunggal, setiap program tunggal yang berjalan pada komputer Anda 211 00:17:42,250 --> 00:17:49,450 memiliki sendiri - mari kita asumsikan 32 bit - ruang alamat benar-benar independen. 212 00:17:49,450 --> 00:17:51,590 Ini adalah ruang alamat. 213 00:17:51,590 --> 00:17:56,220 Memiliki sendiri benar-benar independen 4 gigabyte untuk digunakan. 214 00:17:56,220 --> 00:18:02,220 >> Jadi jika Anda menjalankan 2 program secara bersamaan, program ini melihat 4 gigabyte untuk dirinya sendiri, 215 00:18:02,220 --> 00:18:04,870 Program ini melihat 4 gigabyte untuk dirinya sendiri, 216 00:18:04,870 --> 00:18:07,720 dan itu tidak mungkin untuk program ini untuk dereference pointer 217 00:18:07,720 --> 00:18:10,920 dan berakhir dengan memori dari program ini. 218 00:18:10,920 --> 00:18:18,200 Dan apa memori virtual adalah pemetaan dari ruang alamat proses 219 00:18:18,200 --> 00:18:20,470 hal-hal yang sebenarnya pada RAM. 220 00:18:20,470 --> 00:18:22,940 Jadi terserah kepada sistem operasi Anda untuk mengetahui bahwa, 221 00:18:22,940 --> 00:18:28,080 hey, saat ini pria dereferences oxbfff pointer, yang benar-benar berarti 222 00:18:28,080 --> 00:18:31,040 bahwa ia ingin RAM byte 1000, 223 00:18:31,040 --> 00:18:38,150 sedangkan jika program ini dereferences oxbfff, dia benar-benar ingin RAM byte 10000. 224 00:18:38,150 --> 00:18:41,590 Mereka bisa sewenang-wenang berjauhan. 225 00:18:41,590 --> 00:18:48,730 Ini bahkan benar hal-hal dalam ruang alamat proses tunggal. 226 00:18:48,730 --> 00:18:54,770 Jadi seperti itu melihat semua 4 gigabyte untuk dirinya sendiri, tetapi katakanlah - 227 00:18:54,770 --> 00:18:57,290 [Mahasiswa] Apakah setiap proses tunggal - 228 00:18:57,290 --> 00:19:01,350 Katakanlah Anda memiliki komputer dengan hanya 4 gigabyte RAM. 229 00:19:01,350 --> 00:19:06,430 Apakah setiap proses tunggal melihat 4 gigabyte seluruh? >> Ya. 230 00:19:06,430 --> 00:19:13,060 Tetapi 4 gigabyte yang dilihatnya adalah dusta. 231 00:19:13,060 --> 00:19:20,460 Hanya saja itu berpikir itu memiliki semua memori ini karena tidak tahu proses lain ada. 232 00:19:20,460 --> 00:19:28,140 Ini hanya akan menggunakan memori sebanyak itu benar-benar membutuhkan. 233 00:19:28,140 --> 00:19:32,340 Sistem operasi tidak akan memberikan RAM untuk proses ini 234 00:19:32,340 --> 00:19:35,750 jika tidak menggunakan memori di seluruh wilayah. 235 00:19:35,750 --> 00:19:39,300 Ini tidak akan memberikan memori untuk daerah itu. 236 00:19:39,300 --> 00:19:54,780 Tapi gagasan adalah bahwa - Saya mencoba untuk memikirkan - Saya tidak bisa memikirkan analogi. 237 00:19:54,780 --> 00:19:56,780 Analogi sulit. 238 00:19:57,740 --> 00:20:02,700 Salah satu masalah memori virtual atau salah satu hal itu pemecahan 239 00:20:02,700 --> 00:20:06,810 adalah bahwa proses harus benar-benar menyadari satu sama lain. 240 00:20:06,810 --> 00:20:12,140 Dan sehingga Anda dapat menulis program apapun yang hanya dereferences pointer apapun, 241 00:20:12,140 --> 00:20:19,340 seperti hanya menulis sebuah program yang mengatakan * (ox1234), 242 00:20:19,340 --> 00:20:22,890 dan itulah dereferencing memori alamat 1234. 243 00:20:22,890 --> 00:20:28,870 >> Tapi itu terserah sistem operasi untuk kemudian menerjemahkan apa artinya 1.234. 244 00:20:28,870 --> 00:20:33,960 Jadi jika terjadi 1.234 menjadi alamat memori yang valid untuk proses ini, 245 00:20:33,960 --> 00:20:38,800 seperti itu pada tumpukan atau sesuatu, maka ini akan mengembalikan nilai dari alamat memori 246 00:20:38,800 --> 00:20:41,960 sejauh proses tahu. 247 00:20:41,960 --> 00:20:47,520 Tetapi jika 1234 adalah bukan alamat yang valid, seperti terjadi pada tanah 248 00:20:47,520 --> 00:20:52,910 dalam beberapa bagian kecil dari memori di sini yang berada di luar stack dan di luar tumpukan 249 00:20:52,910 --> 00:20:57,200 dan Anda belum benar-benar digunakan itu, maka saat itulah Anda mendapatkan hal-hal seperti segfaults 250 00:20:57,200 --> 00:21:00,260 karena Anda menyentuh memori bahwa Anda tidak harus menyentuh. 251 00:21:07,180 --> 00:21:09,340 Hal ini juga benar - 252 00:21:09,340 --> 00:21:15,440 Sebuah sistem 32-bit, 32 bit berarti Anda memiliki 32 bit untuk mendefinisikan alamat memori. 253 00:21:15,440 --> 00:21:22,970 Ini sebabnya pointer adalah 8 byte karena 32 bit adalah 8 byte - atau 4 byte. 254 00:21:22,970 --> 00:21:25,250 Pointer 4 byte. 255 00:21:25,250 --> 00:21:33,680 Jadi, ketika Anda melihat pointer seperti oxbfffff, yaitu - 256 00:21:33,680 --> 00:21:40,080 Dalam setiap program yang diberikan Anda hanya dapat membuat setiap pointer sewenang-wenang, 257 00:21:40,080 --> 00:21:46,330 mana saja dari ox0 ke sapi 8 f's - FFFFFFFF. 258 00:21:46,330 --> 00:21:49,180 [Mahasiswa] Bukankah kau bilang mereka 4 byte? >> Ya. 259 00:21:49,180 --> 00:21:52,730 [Mahasiswa] Kemudian setiap byte akan memiliki - >> [Bowden] Heksadesimal. 260 00:21:52,730 --> 00:21:59,360 Heksadesimal - 5, 6, 7, 8. Jadi pointer Anda akan selalu melihat di heksadesimal. 261 00:21:59,360 --> 00:22:01,710 Hanya saja bagaimana kita mengklasifikasikan pointer. 262 00:22:01,710 --> 00:22:05,240 Setiap 2 digit heksadesimal adalah 1 byte. 263 00:22:05,240 --> 00:22:09,600 Jadi ada akan menjadi 8 digit heksadesimal untuk 4 byte. 264 00:22:09,600 --> 00:22:14,190 Jadi setiap pointer tunggal pada sistem 32-bit akan menjadi 4 byte, 265 00:22:14,190 --> 00:22:18,550 yang berarti bahwa dalam proses Anda, Anda dapat membuat setiap 4 byte sewenang-wenang 266 00:22:18,550 --> 00:22:20,550 dan membuat pointer dari itu, 267 00:22:20,550 --> 00:22:32,730 yang berarti bahwa sejauh itu sadar, ia dapat mengatasi suatu keseluruhan 2 ke 32 byte memori. 268 00:22:32,730 --> 00:22:34,760 Meskipun tidak benar-benar memiliki akses ke, 269 00:22:34,760 --> 00:22:40,190 bahkan jika komputer Anda hanya memiliki 512 megabyte, berpikir itu memiliki banyak memori. 270 00:22:40,190 --> 00:22:44,930 Dan sistem operasi cukup pintar bahwa hal itu hanya akan mengalokasikan apa yang sebenarnya Anda butuhkan. 271 00:22:44,930 --> 00:22:49,630 Ini tidak hanya pergi, oh, suatu proses baru: 4 gigs. 272 00:22:49,630 --> 00:22:51,930 >> Ya. >> [Mahasiswa] Apa lembu artinya? Mengapa Anda menulis itu? 273 00:22:51,930 --> 00:22:54,980 Ini hanya simbol untuk heksadesimal. 274 00:22:54,980 --> 00:22:59,590 Ketika Anda melihat awal nomor dengan sapi, hal-hal berturut-turut adalah heksadesimal. 275 00:23:01,930 --> 00:23:05,760 [Mahasiswa] Kau menjelaskan tentang apa yang terjadi ketika sebuah program berakhir. >> Ya. 276 00:23:05,760 --> 00:23:09,480 Apa yang terjadi ketika sebuah program berakhir adalah sistem operasi 277 00:23:09,480 --> 00:23:13,600 hanya menghapus pemetaan yang memiliki untuk memperoleh alamat tersebut, dan hanya itu. 278 00:23:13,600 --> 00:23:17,770 Sistem operasi sekarang dapat hanya memberikan memori yang ke program lain untuk menggunakan. 279 00:23:17,770 --> 00:23:19,490 [Mahasiswa] Oke. 280 00:23:19,490 --> 00:23:24,800 Jadi, ketika Anda mengalokasikan sesuatu di tumpukan atau variabel stack atau global atau apa, 281 00:23:24,800 --> 00:23:27,010 mereka semua hanya menghilang segera setelah program berakhir 282 00:23:27,010 --> 00:23:32,120 karena sistem operasi sekarang bebas untuk memberikan memori yang ke proses lainnya. 283 00:23:32,120 --> 00:23:35,150 [Mahasiswa] Meskipun ada mungkin masih ditulis dalam nilai-nilai? >> Ya. 284 00:23:35,150 --> 00:23:37,740 Nilai-nilai yang mungkin masih ada. 285 00:23:37,740 --> 00:23:41,570 Hanya saja itu akan sulit untuk mendapatkan mereka. 286 00:23:41,570 --> 00:23:45,230 Ini jauh lebih sulit untuk mendapatkan mereka daripada itu adalah untuk mendapatkan file yang dihapus 287 00:23:45,230 --> 00:23:51,450 karena jenis file yang dihapus dari duduk di sana untuk waktu yang lama dan hard drive adalah jauh lebih besar. 288 00:23:51,450 --> 00:23:54,120 Jadi itu akan menimpa bagian yang berbeda dari memori 289 00:23:54,120 --> 00:23:58,640 sebelum hal itu terjadi menimpa sepotong memori bahwa file yang digunakan untuk berada di. 290 00:23:58,640 --> 00:24:04,520 Tapi memori utama, RAM, Anda siklus melalui banyak lebih cepat, 291 00:24:04,520 --> 00:24:08,040 sehingga akan sangat cepat akan ditimpa. 292 00:24:10,300 --> 00:24:13,340 Pertanyaan ini atau hal lain? 293 00:24:13,340 --> 00:24:16,130 [Mahasiswa] Saya memiliki pertanyaan tentang topik yang berbeda. Oke >>. 294 00:24:16,130 --> 00:24:19,060 Apakah ada yang memiliki pertanyaan tentang ini? 295 00:24:20,170 --> 00:24:23,120 >> Oke. Berbeda topik. >> [Mahasiswa] Oke. 296 00:24:23,120 --> 00:24:26,550 Aku akan melalui beberapa tes praktek, 297 00:24:26,550 --> 00:24:30,480 dan dalam salah satu dari mereka itu berbicara tentang sizeof 298 00:24:30,480 --> 00:24:35,630 dan nilai yang ia mengembalikan atau jenis variabel yang berbeda. >> Ya. 299 00:24:35,630 --> 00:24:45,060 Dan mengatakan bahwa kedua int dan panjang baik kembali 4, jadi mereka berdua 4 byte panjang. 300 00:24:45,060 --> 00:24:48,070 Apakah ada perbedaan antara int dan panjang, atau apakah hal yang sama? 301 00:24:48,070 --> 00:24:50,380 Ya, ada perbedaan. 302 00:24:50,380 --> 00:24:52,960 Standar C - 303 00:24:52,960 --> 00:24:54,950 Saya mungkin akan mengacaukan. 304 00:24:54,950 --> 00:24:58,800 Standar C adalah seperti apa C adalah, dokumentasi resmi C. 305 00:24:58,800 --> 00:25:00,340 Ini adalah apa yang dikatakan. 306 00:25:00,340 --> 00:25:08,650 Jadi standar C hanya mengatakan bahwa char akan selamanya dan selalu menjadi 1 byte. 307 00:25:10,470 --> 00:25:19,040 Semuanya setelah itu - pendek selalu hanya didefinisikan sebagai lebih besar dari atau sama dengan char. 308 00:25:19,040 --> 00:25:23,010 Ini mungkin benar-benar lebih besar daripada, tapi tidak positif. 309 00:25:23,010 --> 00:25:31,940 Int hanya didefinisikan sebagai lebih besar dari atau sama dengan singkat. 310 00:25:31,940 --> 00:25:36,210 Dan panjang hanya didefinisikan sebagai lebih besar dari atau sama dengan int. 311 00:25:36,210 --> 00:25:41,600 Dan lama lebih besar dari atau sama dengan panjang. 312 00:25:41,600 --> 00:25:46,610 Jadi satu-satunya standar C mendefinisikan adalah pemesanan relatif segalanya. 313 00:25:46,610 --> 00:25:54,880 Jumlah sebenarnya dari memori yang mengambil hal-hal umumnya sampai dengan implementasi, 314 00:25:54,880 --> 00:25:57,640 tapi itu cukup baik didefinisikan pada saat ini. >> [Mahasiswa] Oke. 315 00:25:57,640 --> 00:26:02,490 Jadi celana pendek hampir selalu akan menjadi 2 byte. 316 00:26:04,920 --> 00:26:09,950 Ints hampir selalu akan menjadi 4 byte. 317 00:26:12,070 --> 00:26:15,340 Rindu Panjang hampir selalu akan menjadi 8 byte. 318 00:26:17,990 --> 00:26:23,160 Dan merindukan, itu tergantung pada apakah Anda menggunakan 32-bit atau sistem 64-bit. 319 00:26:23,160 --> 00:26:27,450 Jadi panjang akan sesuai dengan jenis sistem. 320 00:26:27,450 --> 00:26:31,920 Jika Anda menggunakan sistem 32-bit seperti Appliance, itu akan menjadi 4 byte. 321 00:26:34,530 --> 00:26:42,570 Jika Anda menggunakan 64-bit seperti banyak komputer baru-baru ini, itu akan menjadi 8 byte. 322 00:26:42,570 --> 00:26:45,230 >> Ints hampir selalu 4 byte pada saat ini. 323 00:26:45,230 --> 00:26:47,140 Rindu Panjang hampir selalu 8 byte. 324 00:26:47,140 --> 00:26:50,300 Di masa lalu, ints digunakan untuk hanya 2 byte. 325 00:26:50,300 --> 00:26:56,840 Tapi melihat bahwa ini benar-benar memenuhi semua hubungan yang lebih besar dari dan sama dengan. 326 00:26:56,840 --> 00:27:01,280 Selama sempurna diizinkan untuk menjadi ukuran yang sama sebagai integer, 327 00:27:01,280 --> 00:27:04,030 dan itu juga memungkinkan untuk menjadi ukuran yang sama sebagai lama. 328 00:27:04,030 --> 00:27:11,070 Dan itu hanya begitu kebetulan bahwa pada 99,999% dari sistem, itu akan menjadi sama dengan 329 00:27:11,070 --> 00:27:15,800 baik sebagai int atau lama. Itu hanya tergantung pada 32-bit atau 64-bit. >> [Mahasiswa] Oke. 330 00:27:15,800 --> 00:27:24,600 Dalam mengapung, bagaimana titik desimal yang ditunjuk dalam hal bit? 331 00:27:24,600 --> 00:27:27,160 Seperti sebagai biner? >> Ya. 332 00:27:27,160 --> 00:27:30,570 Anda tidak perlu tahu bahwa untuk CS50. 333 00:27:30,570 --> 00:27:32,960 Anda bahkan tidak belajar bahwa dalam 61. 334 00:27:32,960 --> 00:27:37,350 Anda tidak belajar yang benar-benar dalam kursus apapun. 335 00:27:37,350 --> 00:27:42,740 Ini hanya representasi. 336 00:27:42,740 --> 00:27:45,440 Saya lupa jatah bit yang tepat. 337 00:27:45,440 --> 00:27:53,380 Ide floating point adalah bahwa Anda mengalokasikan sejumlah tertentu dari bit untuk mewakili - 338 00:27:53,380 --> 00:27:56,550 Pada dasarnya, segala sesuatu adalah dalam notasi ilmiah. 339 00:27:56,550 --> 00:28:05,600 Jadi Anda mengalokasikan sejumlah tertentu dari bit untuk mewakili nomor sendiri, seperti 1,2345. 340 00:28:05,600 --> 00:28:10,200 Saya tidak pernah dapat mewakili nomor dengan digit lebih dari 5. 341 00:28:12,200 --> 00:28:26,300 Kemudian Anda juga mengalokasikan sejumlah bit tertentu sehingga cenderung menjadi seperti 342 00:28:26,300 --> 00:28:32,810 Anda hanya bisa naik ke nomor tertentu, seperti itulah eksponen terbesar Anda dapat memiliki, 343 00:28:32,810 --> 00:28:36,190 dan Anda hanya bisa pergi ke suatu eksponen tertentu, 344 00:28:36,190 --> 00:28:38,770 seperti itulah eksponen terkecil Anda dapat memiliki. 345 00:28:38,770 --> 00:28:44,410 >> Saya tidak ingat bit cara yang tepat ditugaskan untuk semua nilai-nilai ini, 346 00:28:44,410 --> 00:28:47,940 namun sejumlah bit yang didedikasikan untuk 1,2345, 347 00:28:47,940 --> 00:28:50,930 lain sejumlah bit yang didedikasikan untuk eksponen, 348 00:28:50,930 --> 00:28:55,670 dan itu hanya mungkin untuk mewakili eksponen dengan ukuran tertentu. 349 00:28:55,670 --> 00:29:01,100 [Mahasiswa] Dan ganda? Apakah itu seperti mengapung ekstra panjang? >> Ya. 350 00:29:01,100 --> 00:29:07,940 Ini adalah hal yang sama seperti pelampung kecuali sekarang Anda menggunakan 8 byte bukan 4 byte. 351 00:29:07,940 --> 00:29:11,960 Sekarang Anda akan dapat menggunakan 9 digit atau 10 digit, 352 00:29:11,960 --> 00:29:16,630 dan ini akan bisa naik ke 300, bukan 100. >> [Mahasiswa] Oke. 353 00:29:16,630 --> 00:29:21,550 Dan mengapung juga 4 byte. >> Ya. 354 00:29:21,550 --> 00:29:27,520 Nah, sekali lagi, itu mungkin tergantung pada pelaksanaan keseluruhan umum, 355 00:29:27,520 --> 00:29:30,610 namun mengapung adalah 4 byte, ganda adalah 8. 356 00:29:30,610 --> 00:29:33,440 Ganda disebut ganda karena mereka dua kali lipat ukuran mengapung. 357 00:29:33,440 --> 00:29:38,380 [Mahasiswa] Oke. Dan apakah ada ganda ganda? >> Tidak ada. 358 00:29:38,380 --> 00:29:43,660 Saya pikir - >> [mahasiswa] Seperti rindu yang lama? >> Ya. Saya rasa tidak. Ya. 359 00:29:43,660 --> 00:29:45,950 [Mahasiswa] Pada tes tahun lalu ada pertanyaan tentang fungsi utama 360 00:29:45,950 --> 00:29:49,490 harus menjadi bagian dari program anda. 361 00:29:49,490 --> 00:29:52,310 Jawabannya adalah bahwa hal itu tidak harus menjadi bagian dari program anda. 362 00:29:52,310 --> 00:29:55,100 Dalam situasi apa? Itulah apa yang saya lihat. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Tampaknya - >> [mahasiswa] Situasi apa? 364 00:29:59,090 --> 00:30:02,880 Apakah Anda memiliki masalah? >> [Mahasiswa] Ya, saya pasti bisa menariknya ke atas. 365 00:30:02,880 --> 00:30:07,910 Tidak harus, secara teknis, tetapi pada dasarnya itu akan menjadi. 366 00:30:07,910 --> 00:30:10,030 [Mahasiswa] Saya melihat satu di tahun yang berbeda itu. 367 00:30:10,030 --> 00:30:16,220 Rasanya seperti Benar atau Salah: A berlaku - >> Oh, c file.? 368 00:30:16,220 --> 00:30:18,790 . [Mahasiswa] Setiap file c harus memiliki - [keduanya berbicara sekaligus - dimengerti] 369 00:30:18,790 --> 00:30:21,120 Oke. Jadi yang terpisah. 370 00:30:21,120 --> 00:30:26,800 >> Sebuah file. C hanya perlu mengandung fungsi. 371 00:30:26,800 --> 00:30:32,400 Anda dapat mengkompilasi sebuah file ke dalam kode mesin, biner, apa pun, 372 00:30:32,400 --> 00:30:36,620 tanpa itu menjadi executable belum. 373 00:30:36,620 --> 00:30:39,420 Sebuah eksekusi yang sah harus memiliki fungsi utama. 374 00:30:39,420 --> 00:30:45,460 Anda dapat menulis 100 fungsi dalam 1 file tapi tidak main 375 00:30:45,460 --> 00:30:48,800 dan kemudian kompilasi yang turun ke biner, 376 00:30:48,800 --> 00:30:54,460 maka Anda menulis file lain yang hanya memiliki utama tetapi panggilan sekelompok fungsi-fungsi 377 00:30:54,460 --> 00:30:56,720 dalam file biner di sini. 378 00:30:56,720 --> 00:31:01,240 Dan jadi ketika Anda membuat executable, itulah yang linker tidak 379 00:31:01,240 --> 00:31:05,960 adalah menggabungkan file-file biner 2 menjadi dieksekusi. 380 00:31:05,960 --> 00:31:11,400 Jadi file. C tidak perlu memiliki fungsi utama sama sekali. 381 00:31:11,400 --> 00:31:19,220 Dan pada basis kode besar Anda akan melihat ribuan file c. Dan 1 file utama. 382 00:31:23,960 --> 00:31:26,110 Lebih banyak pertanyaan? 383 00:31:29,310 --> 00:31:31,940 [Mahasiswa] Ada pertanyaan lain. 384 00:31:31,940 --> 00:31:36,710 Dikatakan membuat adalah kompilator. Benar atau Salah? 385 00:31:36,710 --> 00:31:42,030 Dan jawabannya adalah palsu, dan aku mengerti mengapa hal itu tidak seperti dentang. 386 00:31:42,030 --> 00:31:44,770 Tapi apa yang kita sebut membuat jika itu bukan? 387 00:31:44,770 --> 00:31:49,990 Membuat dasarnya hanya - Saya bisa melihat apa yang mereka sebut itu. 388 00:31:49,990 --> 00:31:52,410 Tapi itu hanya menjalankan perintah. 389 00:31:53,650 --> 00:31:55,650 Membuat. 390 00:31:58,240 --> 00:32:00,870 Saya dapat menarik ini. Ya. 391 00:32:10,110 --> 00:32:13,180 Oh, yeah. Buatlah juga melakukan hal itu. 392 00:32:13,180 --> 00:32:17,170 Ini mengatakan tujuan membuat utilitas adalah untuk menentukan secara otomatis 393 00:32:17,170 --> 00:32:19,610 yang potongan program yang besar perlu dikompilasi ulang 394 00:32:19,610 --> 00:32:22,350 dan mengeluarkan perintah untuk mengkompilasi ulang mereka. 395 00:32:22,350 --> 00:32:27,690 Anda dapat membuat membuat file yang benar-benar besar. 396 00:32:27,690 --> 00:32:33,210 Membuat terlihat pada perangko waktu dari file dan, seperti kami katakan sebelumnya, 397 00:32:33,210 --> 00:32:36,930 Anda dapat mengkompilasi file individual turun, dan itu tidak sampai Anda mendapatkan ke linker 398 00:32:36,930 --> 00:32:39,270 bahwa mereka disatukan dalam dieksekusi. 399 00:32:39,270 --> 00:32:43,810 Jadi jika Anda memiliki 10 file yang berbeda dan Anda membuat perubahan ke 1 dari mereka, 400 00:32:43,810 --> 00:32:47,870 maka apa make yang akan dilakukan hanya mengkompilasi ulang bahwa 1 file 401 00:32:47,870 --> 00:32:50,640 dan kemudian relink semuanya bersama-sama. 402 00:32:50,640 --> 00:32:53,020 Tapi itu jauh lebih bodoh dari itu. 403 00:32:53,020 --> 00:32:55,690 Terserah Anda untuk benar-benar mendefinisikan bahwa itulah yang harus dilakukan. 404 00:32:55,690 --> 00:32:59,560 Ini secara default memiliki kemampuan untuk mengenali hal ini cap waktu, 405 00:32:59,560 --> 00:33:03,220 tetapi Anda bisa menulis file make untuk melakukan apa pun. 406 00:33:03,220 --> 00:33:09,150 Anda dapat menulis membuat file sehingga ketika Anda mengetik membuatnya hanya cd ke direktori lain. 407 00:33:09,150 --> 00:33:15,560 Saya frustrasi karena saya taktik segalanya dalam Appliance saya 408 00:33:15,560 --> 00:33:21,740 dan kemudian saya melihat PDF dari Mac. 409 00:33:21,740 --> 00:33:30,720 >> Jadi saya pergi ke Finder dan saya bisa melakukan Go, Connect to Server, 410 00:33:30,720 --> 00:33:36,950 dan server saya terhubung ke Appliance adalah saya, dan kemudian saya membuka PDF 411 00:33:36,950 --> 00:33:40,190 yang akan dikompilasi oleh LaTeX. 412 00:33:40,190 --> 00:33:49,320 Tapi aku frustrasi karena setiap kali saya butuhkan untuk menyegarkan PDF, 413 00:33:49,320 --> 00:33:53,900 Aku harus menyalinnya ke direktori spesifik yang dapat mengakses 414 00:33:53,900 --> 00:33:57,710 dan semakin menjengkelkan. 415 00:33:57,710 --> 00:34:02,650 Jadi, bukannya saya menulis sebuah file make, yang Anda harus menentukan bagaimana membuat hal-hal. 416 00:34:02,650 --> 00:34:06,130 Bagaimana Anda membuat dalam hal ini adalah PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Sama seperti file make lainnya - atau saya rasa Anda belum melihat file make, 418 00:34:10,090 --> 00:34:13,510 tapi kita miliki dalam Appliance file make global yang hanya mengatakan, 419 00:34:13,510 --> 00:34:16,679 jika Anda melakukan compile sebuah program C, gunakan dentang. 420 00:34:16,679 --> 00:34:20,960 Dan jadi di sini dalam file make saya bahwa saya membuat saya katakan, 421 00:34:20,960 --> 00:34:25,020 file ini Anda akan ingin mengkompilasi dengan PDF LaTeX. 422 00:34:25,020 --> 00:34:27,889 Dan jadi LaTeX PDF yang melakukan compiling. 423 00:34:27,889 --> 00:34:31,880 Membuat tidak kompilasi. Ini hanya menjalankan perintah-perintah dalam urutan saya ditentukan. 424 00:34:31,880 --> 00:34:36,110 Sehingga berjalan LaTeX PDF, itu salinan ke direktori saya ingin disalin ke, 425 00:34:36,110 --> 00:34:38,270 itu cd untuk direktori dan melakukan hal-hal lainnya, 426 00:34:38,270 --> 00:34:42,380 tetapi semua itu tidak akan mengenali ketika perubahan file, 427 00:34:42,380 --> 00:34:45,489 dan jika perubahan, maka akan menjalankan perintah yang seharusnya untuk menjalankan 428 00:34:45,489 --> 00:34:48,760 ketika perubahan file. >> [Mahasiswa] Oke. 429 00:34:50,510 --> 00:34:54,420 Saya tidak tahu di mana file make global bagi saya untuk check it out. 430 00:34:57,210 --> 00:35:04,290 Pertanyaan lain? Apa pun dari masa lalu kuis? Setiap hal pointer? 431 00:35:06,200 --> 00:35:08,730 Ada hal-hal yang halus dengan pointer seperti - 432 00:35:08,730 --> 00:35:10,220 Aku tidak akan dapat menemukan pertanyaan kuis di atasnya - 433 00:35:10,220 --> 00:35:16,250 tapi seperti hal semacam ini. 434 00:35:19,680 --> 00:35:24,060 Pastikan Anda mengerti bahwa ketika saya mengatakan int * x * y - 435 00:35:24,890 --> 00:35:28,130 Ini bukan apa-apa di sini, saya kira. 436 00:35:28,130 --> 00:35:32,140 Tapi seperti * x * y, yaitu 2 variabel yang ada di stack. 437 00:35:32,140 --> 00:35:37,220 Ketika saya mengatakan x = malloc (sizeof (int)), x adalah masih variabel pada stack, 438 00:35:37,220 --> 00:35:41,180 malloc adalah beberapa blok atas di tumpukan, dan kita memiliki titik x ke tumpukan. 439 00:35:41,180 --> 00:35:43,900 >> Jadi sesuatu di titik tumpukan ke tumpukan. 440 00:35:43,900 --> 00:35:48,100 Setiap kali Anda malloc apapun, Anda pasti menyimpannya dalam pointer. 441 00:35:48,100 --> 00:35:55,940 Jadi pointer yang ada di stack, blok malloced adalah di heap. 442 00:35:55,940 --> 00:36:01,240 Banyak orang bingung dan mengatakan int * x = malloc, x adalah di heap. 443 00:36:01,240 --> 00:36:04,100 Tidak Apa x menunjuk adalah di heap. 444 00:36:04,100 --> 00:36:08,540 x itu sendiri adalah pada stack, kecuali untuk alasan apapun Anda telah x menjadi variabel global, 445 00:36:08,540 --> 00:36:11,960 dalam hal ini akan terjadi di wilayah lain di memori. 446 00:36:13,450 --> 00:36:20,820 Jadi mencatat, diagram ini kotak dan anak panah cukup umum untuk kuis. 447 00:36:20,820 --> 00:36:25,740 Atau jika tidak pada kuis 0, itu akan berada di kuis 1. 448 00:36:27,570 --> 00:36:31,940 Anda harus tahu semua ini, langkah-langkah dalam menyusun 449 00:36:31,940 --> 00:36:35,740 karena Anda harus menjawab pertanyaan pada mereka. Ya. 450 00:36:35,740 --> 00:36:38,940 [Mahasiswa] Bisakah kita pergi ke langkah-langkah - >> Tentu. 451 00:36:48,340 --> 00:36:58,640 Sebelum langkah dan menyusun kita memiliki preprocessing, 452 00:36:58,640 --> 00:37:16,750 kompilasi, perakitan, dan menghubungkan. 453 00:37:16,750 --> 00:37:21,480 Preprocessing. Apa artinya itu lakukan? 454 00:37:29,720 --> 00:37:32,290 Ini adalah langkah termudah dalam - baik, tidak seperti - 455 00:37:32,290 --> 00:37:35,770 itu tidak berarti itu harus jelas, tetapi itu adalah langkah termudah. 456 00:37:35,770 --> 00:37:38,410 Kalian bisa menerapkannya sendiri. Ya. 457 00:37:38,410 --> 00:37:43,410 [Mahasiswa] Ambil apa yang Anda miliki dalam Anda termasuk seperti ini dan itu salinan dan kemudian juga mendefinisikan. 458 00:37:43,410 --> 00:37:49,250 Tampaknya untuk hal-hal seperti # include dan # define, 459 00:37:49,250 --> 00:37:53,800 dan hanya salinan dan pasta apa yang mereka benar-benar berarti. 460 00:37:53,800 --> 00:37:59,240 Jadi ketika Anda mengatakan # include cs50.h, preprocessor adalah menyalin dan menyisipkan cs50.h 461 00:37:59,240 --> 00:38:01,030 ke baris tersebut. 462 00:38:01,030 --> 00:38:06,640 Ketika Anda mengatakan # define x menjadi 4, preprocessor melewati seluruh program 463 00:38:06,640 --> 00:38:10,400 dan menggantikan semua contoh x dengan 4. 464 00:38:10,400 --> 00:38:17,530 Jadi preprocessor mengambil file C valid dan output file C valid 465 00:38:17,530 --> 00:38:20,300 mana hal-hal telah disalin dan disisipkan. 466 00:38:20,300 --> 00:38:24,230 Jadi sekarang kompilasi. Apa artinya itu lakukan? 467 00:38:25,940 --> 00:38:28,210 [Mahasiswa] It goes dari C ke biner. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Ia tidak pergi jauh-jauh ke biner. 469 00:38:30,970 --> 00:38:34,220 [Mahasiswa] Untuk kode mesin itu? >> Ini bukan kode mesin. 470 00:38:34,220 --> 00:38:35,700 [Mahasiswa] Majelis? >> Majelis. 471 00:38:35,700 --> 00:38:38,890 Ini pergi ke Majelis sebelum pergi semua jalan ke kode C, 472 00:38:38,890 --> 00:38:45,010 dan bahasa yang paling melakukan sesuatu seperti ini. 473 00:38:47,740 --> 00:38:50,590 Pilih bahasa tingkat tinggi, dan jika Anda akan melakukan kompilasi, 474 00:38:50,590 --> 00:38:52,390 kemungkinan untuk mengkompilasi dalam langkah-langkah. 475 00:38:52,390 --> 00:38:58,140 Pertama itu akan mengkompilasi Python ke C, maka akan mengkompilasi C ke Majelis, 476 00:38:58,140 --> 00:39:01,600 dan kemudian Majelis akan mendapatkan diterjemahkan ke biner. 477 00:39:01,600 --> 00:39:07,800 Jadi kompilasi akan membawanya dari C ke Majelis. 478 00:39:07,800 --> 00:39:12,130 Kata kompilasi biasanya berarti membawanya dari tingkat yang lebih tinggi 479 00:39:12,130 --> 00:39:14,340 ke bahasa pemrograman tingkat yang lebih rendah. 480 00:39:14,340 --> 00:39:19,190 Jadi ini adalah satu-satunya langkah dalam penyusunan mana Anda mulai dengan bahasa tingkat tinggi 481 00:39:19,190 --> 00:39:23,270 dan berakhir dalam bahasa tingkat rendah, dan itulah sebabnya langkah ini disebut kompilasi. 482 00:39:25,280 --> 00:39:33,370 [Mahasiswa] Selama kompilasi, mari kita mengatakan bahwa Anda telah melakukan # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Akankah compiler mengkompilasi ulang yang cs50.h, seperti fungsi yang ada di sana, 484 00:39:42,190 --> 00:39:45,280 dan menterjemahkannya menjadi kode Majelis juga, 485 00:39:45,280 --> 00:39:50,830 atau akan copy dan paste sesuatu yang sudah pre-Majelis? 486 00:39:50,830 --> 00:39:56,910 cs50.h akan cukup banyak tidak pernah berakhir di Majelis. 487 00:39:59,740 --> 00:40:03,680 Hal-hal seperti prototipe fungsi dan hal-hal yang hanya untuk Anda untuk berhati-hati. 488 00:40:03,680 --> 00:40:09,270 Ini menjamin bahwa kompilator dapat memeriksa hal-hal seperti Anda memanggil fungsi 489 00:40:09,270 --> 00:40:12,910 dengan jenis pengembalian yang tepat dan argumen yang tepat dan barang-barang. 490 00:40:12,910 --> 00:40:18,350 >> Jadi cs50.h akan preproses ke dalam file, dan kemudian ketika itu kompilasi 491 00:40:18,350 --> 00:40:22,310 itu pada dasarnya dibuang setelah memastikan bahwa segala sesuatu sedang disebut dengan benar. 492 00:40:22,310 --> 00:40:29,410 Tapi fungsi yang didefinisikan di perpustakaan CS50, yang terpisah dari cs50.h, 493 00:40:29,410 --> 00:40:33,610 mereka tidak akan dikompilasi secara terpisah. 494 00:40:33,610 --> 00:40:37,270 Yang benar-benar akan turun pada langkah menghubungkan, jadi kita akan mendapatkan bahwa dalam satu detik. 495 00:40:37,270 --> 00:40:40,100 Tapi pertama-tama, apa yang perakitan? 496 00:40:41,850 --> 00:40:44,500 [Mahasiswa] Majelis ke biner? >> Ya. 497 00:40:46,300 --> 00:40:48,190 Perakitan. 498 00:40:48,190 --> 00:40:54,710 Kami tidak menyebutnya kompilasi karena Majelis cukup banyak terjemahan murni biner. 499 00:40:54,710 --> 00:41:00,230 Ada logika yang sangat sedikit pergi dari Majelis ke biner. 500 00:41:00,230 --> 00:41:03,180 Ini seperti melihat ke atas dalam sebuah tabel, oh, kita memiliki instruksi ini; 501 00:41:03,180 --> 00:41:06,290 yang sesuai dengan biner 01110. 502 00:41:10,200 --> 00:41:15,230 Dan sehingga file yang merakit umumnya output yang. O file. 503 00:41:15,230 --> 00:41:19,020 Dan o file. Adalah apa yang kita katakan sebelumnya, 504 00:41:19,020 --> 00:41:21,570 bagaimana file tidak perlu memiliki fungsi utama. 505 00:41:21,570 --> 00:41:27,640 File apapun dapat dikompilasi ke file o. Asalkan itu file C valid. 506 00:41:27,640 --> 00:41:30,300 Hal ini dapat dikompilasi ke. O. 507 00:41:30,300 --> 00:41:43,030 Sekarang, menghubungkan adalah apa yang sebenarnya membawa sekelompok file o dan. Membawa mereka ke dieksekusi. 508 00:41:43,030 --> 00:41:51,110 Dan jadi apa menghubungkan lakukan adalah Anda bisa memikirkan perpustakaan CS50 sebagai file o.. 509 00:41:51,110 --> 00:41:56,980 Ini adalah file biner yang sudah dikompilasi. 510 00:41:56,980 --> 00:42:03,530 Dan jadi ketika Anda mengkompilasi file Anda, Anda hello.c, yang menyerukan GetString, 511 00:42:03,530 --> 00:42:06,360 hello.c akan dikompilasi ke hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o sekarang dalam biner. 513 00:42:08,910 --> 00:42:12,830 Menggunakan GetString, sehingga perlu untuk pergi ke cs50.o, 514 00:42:12,830 --> 00:42:16,390 dan linker smooshes mereka bersama-sama dan salinan GetString ke dalam file ini 515 00:42:16,390 --> 00:42:20,640 dan keluar dengan executable yang memiliki semua fungsi yang dibutuhkan. 516 00:42:20,640 --> 00:42:32,620 Jadi cs50.o sebenarnya bukan file O, tapi itu cukup dekat bahwa tidak ada perbedaan mendasar. 517 00:42:32,620 --> 00:42:36,880 Jadi menghubungkan hanya membawa sekelompok file bersama-sama 518 00:42:36,880 --> 00:42:41,390 yang terpisah berisi semua fungsi saya harus menggunakan 519 00:42:41,390 --> 00:42:46,120 dan menciptakan executable yang benar-benar akan berjalan. 520 00:42:48,420 --> 00:42:50,780 >> Dan sehingga juga apa yang kita katakan sebelumnya 521 00:42:50,780 --> 00:42:55,970 di mana Anda dapat memiliki 1000. file c, Anda kompilasi mereka semua ke file o,. 522 00:42:55,970 --> 00:43:00,040 yang mungkin akan memakan waktu cukup lama, maka Anda mengubah 1. berkas c. 523 00:43:00,040 --> 00:43:05,480 Anda hanya perlu mengkompilasi ulang bahwa 1. Berkas c dan kemudian segala sesuatu yang lain Relink, 524 00:43:05,480 --> 00:43:07,690 menghubungkan semuanya kembali bersama-sama. 525 00:43:09,580 --> 00:43:11,430 [Mahasiswa] Ketika kita menghubungkan kita menulis lcs50? 526 00:43:11,430 --> 00:43:20,510 Ya, jadi-lcs50. Itu sinyal bendera ke linker yang harus Anda menghubungkan di perpustakaan itu. 527 00:43:26,680 --> 00:43:28,910 Pertanyaan? 528 00:43:41,310 --> 00:43:46,860 Apakah kita pergi selama biner selain itu 5 detik di kuliah pertama? 529 00:43:50,130 --> 00:43:53,010 Saya rasa tidak. 530 00:43:55,530 --> 00:43:58,820 Anda harus mengetahui semua Os besar yang kita telah melebihi, 531 00:43:58,820 --> 00:44:02,670 dan Anda harus dapat, jika kita memberi Anda fungsi, 532 00:44:02,670 --> 00:44:09,410 Anda harus dapat mengatakan itu O besar, kira-kira. Atau juga, big O kasar. 533 00:44:09,410 --> 00:44:15,300 Jadi jika Anda melihat bersarang untuk loop perulangan atas jumlah yang sama dari hal-hal, 534 00:44:15,300 --> 00:44:22,260 seperti int i, i > [mahasiswa] n kuadrat. >> Cenderung menjadi n kuadrat. 535 00:44:22,260 --> 00:44:25,280 Jika Anda telah tiga bersarang, itu cenderung menjadi n potong dadu. 536 00:44:25,280 --> 00:44:29,330 Jadi hal semacam itu Anda harus dapat menunjukkan dengan segera. 537 00:44:29,330 --> 00:44:33,890 Anda perlu tahu insertion sort dan bubble sort dan menggabungkan mengurutkan dan semua orang. 538 00:44:33,890 --> 00:44:41,420 Lebih mudah untuk memahami mengapa mereka adalah mereka n kuadrat dan n log n dan semua itu 539 00:44:41,420 --> 00:44:47,810 karena saya pikir ada pada kuis satu tahun di mana kita pada dasarnya memberi Anda 540 00:44:47,810 --> 00:44:55,050 sebuah implementasi dari bubble sort dan berkata, "Apa waktu berjalan dari fungsi ini?" 541 00:44:55,050 --> 00:45:01,020 Jadi jika Anda mengenalinya sebagai semacam gelembung, maka anda dapat langsung katakan n kuadrat. 542 00:45:01,020 --> 00:45:05,470 Tetapi jika Anda hanya melihat itu, Anda bahkan tidak perlu untuk mewujudkan semacam gelembung itu; 543 00:45:05,470 --> 00:45:08,990 Anda hanya bisa mengatakan ini adalah melakukan ini dan ini. Ini adalah n kuadrat. 544 00:45:12,350 --> 00:45:14,710 [Mahasiswa] Apakah ada contoh yang sulit Anda bisa datang dengan, 545 00:45:14,710 --> 00:45:20,370 seperti ide yang sama mencari tahu? 546 00:45:20,370 --> 00:45:24,450 >> Saya tidak berpikir kita akan memberikan contoh-contoh yang sulit. 547 00:45:24,450 --> 00:45:30,180 Hal bubble sort adalah tentang sekuat kita akan pergi, 548 00:45:30,180 --> 00:45:36,280 dan bahkan, selama Anda memahami bahwa Anda iterasi atas array 549 00:45:36,280 --> 00:45:41,670 untuk setiap elemen dalam array, yang akan menjadi sesuatu yang n kuadrat. 550 00:45:45,370 --> 00:45:49,940 Ada pertanyaan umum, seperti di sini kita memiliki - Oh. 551 00:45:55,290 --> 00:45:58,530 Beberapa hari yang lalu, Doug mengaku, "Saya telah menemukan sebuah algoritma yang dapat mengurutkan array 552 00:45:58,530 --> 00:46:01,780 "Nomor n dalam O (log n) waktu!" 553 00:46:01,780 --> 00:46:04,900 Jadi bagaimana kita tahu itu mustahil? 554 00:46:04,900 --> 00:46:08,850 [Respon siswa terdengar] >> Ya. 555 00:46:08,850 --> 00:46:13,710 Paling tidak, Anda harus menyentuh setiap elemen dalam array, 556 00:46:13,710 --> 00:46:16,210 sehingga tidak mungkin untuk mengurutkan array - 557 00:46:16,210 --> 00:46:20,850 Jika semuanya adalah dalam rangka unsorted, maka Anda akan menyentuh segala sesuatu di array, 558 00:46:20,850 --> 00:46:25,320 sehingga tidak mungkin untuk melakukannya dalam waktu kurang dari O n. 559 00:46:27,430 --> 00:46:30,340 [Mahasiswa] Anda menunjukkan kepada kita bahwa contoh mampu melakukannya di O n 560 00:46:30,340 --> 00:46:33,920 jika Anda menggunakan banyak memori. >> Ya. 561 00:46:33,920 --> 00:46:37,970 Dan ltu - aku lupa apa ltu - Apakah menghitung sort? 562 00:46:47,360 --> 00:46:51,330 Hmm. Itu adalah algoritma sorting integer. 563 00:46:59,850 --> 00:47:05,100 Saya sedang mencari nama khusus untuk ini yang saya tidak bisa ingat minggu lalu. 564 00:47:05,100 --> 00:47:13,000 Ya. Ini adalah jenis dari jenis yang dapat mencapai hal-hal besar di O n. 565 00:47:13,000 --> 00:47:18,430 Tetapi ada keterbatasan, seperti Anda hanya dapat menggunakan bilangan bulat sampai jumlah tertentu. 566 00:47:20,870 --> 00:47:24,560 Ditambah jika Anda mencoba untuk mengurutkan ltu sesuatu - 567 00:47:24,560 --> 00:47:30,750 Jika array adalah 012, -12, 151, 4 juta, 568 00:47:30,750 --> 00:47:35,120 maka elemen tunggal akan benar-benar merusak seluruh penyortiran. 569 00:47:42,060 --> 00:47:44,030 >> Pertanyaan? 570 00:47:49,480 --> 00:47:58,870 [Mahasiswa] Jika Anda memiliki fungsi rekursif dan itu hanya membuat panggilan rekursif 571 00:47:58,870 --> 00:48:02,230 dalam pernyataan kembali, itulah ekor rekursif, 572 00:48:02,230 --> 00:48:07,360 dan sehingga akan tidak menggunakan memori lebih selama runtime 573 00:48:07,360 --> 00:48:12,550 atau setidaknya akan menggunakan memori sebanding sebagai solusi iteratif? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Ya. 575 00:48:14,530 --> 00:48:19,840 Ini mungkin akan menjadi agak lambat, tapi tidak benar-benar. 576 00:48:19,840 --> 00:48:23,290 Tail rekursif cukup bagus. 577 00:48:23,290 --> 00:48:32,640 Melihat kembali pada frame stack, katakanlah kita memiliki utama 578 00:48:32,640 --> 00:48:42,920 dan kami memiliki bar int (int x) atau sesuatu. 579 00:48:42,920 --> 00:48:52,310 Ini bukan fungsi rekursif yang sempurna, tapi kembali bar (x - 1). 580 00:48:52,310 --> 00:48:57,620 Jadi jelas, ini cacat. Anda perlu kasus dasar dan barang-barang. 581 00:48:57,620 --> 00:49:00,360 Tapi ide di sini adalah bahwa ini adalah ekor rekursif, 582 00:49:00,360 --> 00:49:06,020 yang berarti ketika bar utama panggilan itu akan mendapatkan stack frame nya. 583 00:49:09,550 --> 00:49:12,440 Dalam stack frame ada akan menjadi blok kecil memori 584 00:49:12,440 --> 00:49:17,490 yang sesuai dengan argumen x nya. 585 00:49:17,490 --> 00:49:25,840 Dan jadi mari kita katakan utama terjadi untuk memanggil bar (100); 586 00:49:25,840 --> 00:49:30,050 Jadi x akan mulai keluar sebagai 100. 587 00:49:30,050 --> 00:49:35,660 Jika compiler mengakui bahwa ini adalah fungsi rekursif ekor, 588 00:49:35,660 --> 00:49:38,540 maka ketika bar membuat panggilan rekursif untuk bar, 589 00:49:38,540 --> 00:49:45,490 alih-alih membuat stack frame baru, yang mana tumpukan mulai tumbuh sebagian besar, 590 00:49:45,490 --> 00:49:48,220 akhirnya akan berjalan ke tumpukan dan kemudian Anda mendapatkan segfaults 591 00:49:48,220 --> 00:49:51,590 karena memori mulai bertabrakan. 592 00:49:51,590 --> 00:49:54,830 >> Jadi daripada membuat stack frame sendiri, dapat mewujudkan, 593 00:49:54,830 --> 00:49:59,080 hey, saya tidak pernah benar-benar perlu untuk kembali ke stack frame, 594 00:49:59,080 --> 00:50:08,040 jadi aku malah hanya akan mengganti argumen ini dengan 99 dan kemudian mulai bar di seluruh. 595 00:50:08,040 --> 00:50:11,810 Dan kemudian akan melakukannya lagi dan itu akan mencapai bar kembali (x - 1), 596 00:50:11,810 --> 00:50:17,320 dan bukannya membuat stack frame baru, itu hanya akan menggantikan argumen saat ini dengan 98 597 00:50:17,320 --> 00:50:20,740 dan kemudian melompat kembali ke awal dari bar. 598 00:50:23,860 --> 00:50:30,430 Mereka operasi, menggantikan bahwa nilai 1 pada stack dan melompat kembali ke awal, 599 00:50:30,430 --> 00:50:32,430 cukup efisien. 600 00:50:32,430 --> 00:50:41,500 Jadi tidak hanya ini penggunaan memori yang sama sebagai fungsi terpisah yang iteratif 601 00:50:41,500 --> 00:50:45,390 karena Anda hanya menggunakan 1 stack frame, tetapi Anda tidak menderita kerugian 602 00:50:45,390 --> 00:50:47,240 karena harus memanggil fungsi-fungsi. 603 00:50:47,240 --> 00:50:50,240 Memanggil fungsi dapat menjadi agak mahal karena harus melakukan semua konfigurasi ini 604 00:50:50,240 --> 00:50:52,470 dan teardown dan semua barang-barang ini. 605 00:50:52,470 --> 00:50:58,160 Jadi ini rekursi ekor baik. 606 00:50:58,160 --> 00:51:01,170 [Mahasiswa] Mengapa tidak menciptakan langkah baru? 607 00:51:01,170 --> 00:51:02,980 Karena menyadari itu tidak perlu. 608 00:51:02,980 --> 00:51:07,800 Panggilan ke bar hanya mengembalikan panggilan rekursif. 609 00:51:07,800 --> 00:51:12,220 Jadi tidak perlu melakukan apa-apa dengan nilai kembali. 610 00:51:12,220 --> 00:51:15,120 Ini hanya akan segera mengembalikannya. 611 00:51:15,120 --> 00:51:20,530 Jadi itu hanya akan menggantikan argumen sendiri dan memulai dari awal. 612 00:51:20,530 --> 00:51:25,780 Dan juga, jika Anda tidak memiliki versi rekursif ekor, 613 00:51:25,780 --> 00:51:31,460 maka Anda mendapatkan semua bar di mana ketika bar ini kembali 614 00:51:31,460 --> 00:51:36,010 itu harus mengembalikan nilai untuk yang satu ini, maka bar segera kembali 615 00:51:36,010 --> 00:51:39,620 dan mengembalikan nilainya ke satu ini, maka itu hanya akan segera kembali 616 00:51:39,620 --> 00:51:41,350 dan mengembalikan nilainya ke satu ini. 617 00:51:41,350 --> 00:51:45,350 Jadi Anda menghemat ini bermunculan semua hal off dari stack 618 00:51:45,350 --> 00:51:48,730 karena nilai kembali hanya akan melewati sepanjang jalan kembali pula. 619 00:51:48,730 --> 00:51:55,400 Jadi mengapa tidak hanya mengganti argumen kami dengan argumen diperbarui dan memulai lagi? 620 00:51:57,460 --> 00:52:01,150 Jika fungsi ini tidak rekursif ekor, jika Anda melakukan sesuatu seperti - 621 00:52:01,150 --> 00:52:07,530 [Mahasiswa] jika bar (x + 1). >> Ya. 622 00:52:07,530 --> 00:52:11,770 >> Jadi jika Anda memasukkannya ke dalam kondisi, maka Anda melakukan sesuatu dengan nilai kembali. 623 00:52:11,770 --> 00:52:16,260 Atau bahkan jika Anda hanya melakukan pengembalian 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Jadi sekarang bar (x - 1) perlu untuk kembali dalam rangka untuk itu untuk menghitung 2 kali nilai, 625 00:52:23,560 --> 00:52:26,140 jadi sekarang itu tidak perlu stack frame terpisah sendiri, 626 00:52:26,140 --> 00:52:31,180 dan sekarang, tidak peduli seberapa keras Anda mencoba, Anda akan perlu - 627 00:52:31,180 --> 00:52:34,410 Ini bukan rekursif ekor. 628 00:52:34,410 --> 00:52:37,590 [Mahasiswa] Apakah saya mencoba untuk membawa rekursi untuk bertujuan untuk rekursi ekor - 629 00:52:37,590 --> 00:52:41,450 [Bowden] Dalam dunia yang ideal, tetapi dalam CS50 Anda tidak perlu. 630 00:52:43,780 --> 00:52:49,280 Dalam rangka untuk mendapatkan rekursi ekor, pada umumnya, Anda membuat sebuah argumen tambahan 631 00:52:49,280 --> 00:52:53,550 di mana bar akan mengambil x int ke y 632 00:52:53,550 --> 00:52:56,990 dan y sesuai dengan hal utama yang Anda ingin kembali. 633 00:52:56,990 --> 00:53:03,650 Jadi ini Anda akan kembali bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Jadi itu hanya tingkat tinggi bagaimana Anda mengubah sesuatu menjadi ekor rekursif. 635 00:53:09,810 --> 00:53:13,790 Namun argumen tambahan - 636 00:53:13,790 --> 00:53:17,410 Dan kemudian pada akhirnya ketika Anda mencapai kasus dasar Anda, Anda hanya mengembalikan y 637 00:53:17,410 --> 00:53:22,740 karena Anda telah terakumulasi sepanjang waktu nilai pengembalian yang Anda inginkan. 638 00:53:22,740 --> 00:53:27,280 Anda jenis telah melakukannya iteratif tetapi menggunakan panggilan rekursif. 639 00:53:32,510 --> 00:53:34,900 Pertanyaan? 640 00:53:34,900 --> 00:53:39,890 [Mahasiswa] Mungkin tentang aritmatika pointer, seperti ketika menggunakan string. Tentu >>. 641 00:53:39,890 --> 00:53:43,610 Pointer aritmatika. 642 00:53:43,610 --> 00:53:48,440 Bila menggunakan string itu mudah karena string adalah bintang char, 643 00:53:48,440 --> 00:53:51,860 karakter yang selamanya dan selalu satu byte, 644 00:53:51,860 --> 00:53:57,540 dan sebagainya aritmatika pointer setara dengan aritmatika biasa saat Anda sedang berhadapan dengan string. 645 00:53:57,540 --> 00:54:08,790 Mari kita hanya mengatakan char * s = "halo". 646 00:54:08,790 --> 00:54:11,430 Jadi kita memiliki blok dalam memori. 647 00:54:19,490 --> 00:54:22,380 Perlu 6 byte karena Anda selalu membutuhkan terminator nol. 648 00:54:22,380 --> 00:54:28,620 Dan char * s akan menunjuk ke awal array ini. 649 00:54:28,620 --> 00:54:32,830 Jadi s menunjuk ada. 650 00:54:32,830 --> 00:54:36,710 Sekarang, hal ini pada dasarnya adalah bagaimana Array setiap bekerja, 651 00:54:36,710 --> 00:54:40,780 terlepas dari apakah itu kembali oleh malloc atau apakah itu di stack. 652 00:54:40,780 --> 00:54:47,110 Array Setiap dasarnya adalah pointer ke awal array, 653 00:54:47,110 --> 00:54:53,640 dan kemudian setiap operasi array, pengindeksan apapun, hanya masuk ke array yang offset tertentu. 654 00:54:53,640 --> 00:55:05,360 >> Jadi ketika saya mengatakan sesuatu seperti s [3], ini akan s dan menghitung 3 chars masuk 655 00:55:05,360 --> 00:55:12,490 Jadi s [3], kita memiliki 0, 1, 2, 3, maka s [3] akan merujuk ke l ini. 656 00:55:12,490 --> 00:55:20,460 [Mahasiswa] Dan kita bisa mencapai nilai yang sama dengan melakukan s + 3 dan kemudian Bintang kurung? 657 00:55:20,460 --> 00:55:22,570 Ya. 658 00:55:22,570 --> 00:55:26,010 Hal ini setara dengan * (s + 3); 659 00:55:26,010 --> 00:55:31,240 dan itu selamanya dan selalu setara tidak peduli apa yang Anda lakukan. 660 00:55:31,240 --> 00:55:34,070 Anda tidak perlu menggunakan sintaks braket. 661 00:55:34,070 --> 00:55:37,770 Anda selalu dapat menggunakan * (s + 3) sintaks. 662 00:55:37,770 --> 00:55:40,180 Orang-orang cenderung menyukai sintaks braket, meskipun. 663 00:55:40,180 --> 00:55:43,860 [Mahasiswa] Jadi semua array yang sebenarnya hanya pointer. 664 00:55:43,860 --> 00:55:53,630 Ada perbedaan sedikit ketika saya mengatakan int x [4]; >> [mahasiswa] Apakah yang menciptakan memori? 665 00:55:53,630 --> 00:56:03,320 [Bowden] Itu akan membuat 4 ints di stack, sehingga 16 byte keseluruhan. 666 00:56:03,320 --> 00:56:05,700 Ini akan membuat 16 byte pada stack. 667 00:56:05,700 --> 00:56:09,190 x tidak disimpan di mana saja. 668 00:56:09,190 --> 00:56:13,420 Ini hanyalah simbol mengacu pada awal hal. 669 00:56:13,420 --> 00:56:17,680 Karena Anda menyatakan array dalam fungsi ini, 670 00:56:17,680 --> 00:56:22,340 apa compiler akan lakukan adalah hanya mengganti semua contoh variabel x 671 00:56:22,340 --> 00:56:26,400 dengan mana itu terjadi memilih untuk menempatkan 16 byte. 672 00:56:26,400 --> 00:56:30,040 Hal ini tidak bisa melakukan itu dengan char * s karena s merupakan pointer yang sebenarnya. 673 00:56:30,040 --> 00:56:32,380 Hal ini bebas untuk kemudian menunjuk ke hal-hal lain. 674 00:56:32,380 --> 00:56:36,140 x adalah sebuah konstanta. Anda tidak dapat memiliki sebuah titik ke array yang berbeda. >> [Mahasiswa] Oke. 675 00:56:36,140 --> 00:56:43,420 Tapi ide ini, pengindeksan ini, adalah sama terlepas dari apakah itu array tradisional 676 00:56:43,420 --> 00:56:48,230 atau jika itu adalah pointer ke sesuatu atau jika itu adalah pointer ke array malloced. 677 00:56:48,230 --> 00:56:59,770 Dan pada kenyataannya, itu adalah supaya setara bahwa juga hal yang sama. 678 00:56:59,770 --> 00:57:05,440 Ini sebenarnya hanya menerjemahkan apa yang ada di dalam tanda kurung dan apa yang tersisa dari kurung, 679 00:57:05,440 --> 00:57:07,970 menambahkan mereka bersama-sama, dan dereferences. 680 00:57:07,970 --> 00:57:14,710 Jadi ini sama validnya dengan * (s + 3) atau s [3]. 681 00:57:16,210 --> 00:57:22,090 [Mahasiswa] Dapatkah Anda memiliki pointer yang menunjuk ke 2-dimensi array? 682 00:57:22,090 --> 00:57:27,380 >> Lebih sulit. Secara tradisional, tidak. 683 00:57:27,380 --> 00:57:34,720 Sebuah array 2-dimensi hanyalah sebuah array 1 dimensi dengan beberapa sintaks yang nyaman 684 00:57:34,720 --> 00:57:54,110 karena ketika saya mengatakan int x [3] [3], ini benar-benar hanya 1 array dengan nilai 9. 685 00:57:55,500 --> 00:58:03,000 Dan jadi ketika saya indeks, compiler tahu apa yang saya maksud. 686 00:58:03,000 --> 00:58:13,090 Jika saya mengatakan x [1] [2], ia tahu aku ingin pergi ke baris kedua, sehingga akan melewati 3 pertama, 687 00:58:13,090 --> 00:58:17,460 dan kemudian ingin hal kedua itu, jadi itu akan mendapatkan satu ini. 688 00:58:17,460 --> 00:58:20,480 Tapi itu masih hanya satu array dimensi. 689 00:58:20,480 --> 00:58:23,660 Dan jadi jika saya ingin menetapkan pointer ke array, 690 00:58:23,660 --> 00:58:29,770 Saya akan mengatakan int * p = x; 691 00:58:29,770 --> 00:58:33,220 Jenis x adalah hanya - 692 00:58:33,220 --> 00:58:38,280 Ini jenis mengatakan kasar x karena hanya simbol dan itu bukan sebuah variabel yang sebenarnya, 693 00:58:38,280 --> 00:58:40,140 tapi itu hanya sebuah * int. 694 00:58:40,140 --> 00:58:44,840 x adalah hanya pointer ke awal ini. >> [Mahasiswa] Oke. 695 00:58:44,840 --> 00:58:52,560 Dan jadi saya tidak akan dapat mengakses [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Saya pikir ada sintaks khusus untuk menyatakan pointer, 697 00:58:58,370 --> 00:59:12,480 sesuatu yang konyol seperti int (* p [-. sesuatu yang benar-benar konyol saya bahkan tidak tahu. 698 00:59:12,480 --> 00:59:17,090 Tapi ada sintaks untuk menyatakan pointer seperti dengan tanda kurung dan hal. 699 00:59:17,090 --> 00:59:22,960 Mungkin tidak bahkan membiarkan Anda melakukan itu. 700 00:59:22,960 --> 00:59:26,640 Aku bisa melihat kembali pada sesuatu yang akan mengatakan yang sebenarnya. 701 00:59:26,640 --> 00:59:34,160 Aku akan mencarinya nanti, jika ada sintaks untuk titik. Tapi Anda tidak akan pernah melihatnya. 702 00:59:34,160 --> 00:59:39,670 Dan bahkan sintaks begitu kuno bahwa jika Anda menggunakannya, orang akan bingung. 703 00:59:39,670 --> 00:59:43,540 Array multidimensi cukup langka seperti itu. 704 00:59:43,540 --> 00:59:44,630 Anda cukup banyak - 705 00:59:44,630 --> 00:59:48,490 Nah, jika Anda melakukan hal-hal matriks itu tidak akan menjadi langka, 706 00:59:48,490 --> 00:59:56,730 tapi di C Anda jarang akan menggunakan array multidimensi. 707 00:59:57,630 --> 01:00:00,470 Ya. >> [Mahasiswa] Katakanlah Anda memiliki array yang sangat panjang. 708 01:00:00,470 --> 01:00:03,900 >> Jadi dalam memori virtual akan muncul untuk menjadi semua berturut-turut, 709 01:00:03,900 --> 01:00:05,640 seperti elemen yang tepat di samping satu sama lain, 710 01:00:05,640 --> 01:00:08,770 tetapi dalam memori fisik, apakah mungkin untuk itu harus berpisah? >> Ya. 711 01:00:08,770 --> 01:00:16,860 Bagaimana maya bekerja memori itu hanya memisahkan - 712 01:00:19,220 --> 01:00:24,860 Unit alokasi adalah halaman, yang cenderung menjadi 4 kilobyte, 713 01:00:24,860 --> 01:00:29,680 dan jadi ketika proses berkata, hey, saya ingin menggunakan memori ini, 714 01:00:29,680 --> 01:00:35,970 sistem operasi akan mengalokasikan 4 kilobyte untuk itu blok sedikit memori. 715 01:00:35,970 --> 01:00:39,100 Bahkan jika Anda hanya menggunakan satu byte kecil tunggal di seluruh blok memori, 716 01:00:39,100 --> 01:00:42,850 sistem operasi akan memberikannya 4 kilobyte penuh. 717 01:00:42,850 --> 01:00:49,410 Jadi apa artinya ini adalah aku bisa - katakanlah ini adalah stack saya. 718 01:00:49,410 --> 01:00:53,180 Tumpukan ini dapat dipisahkan. Saya tumpukan bisa megabyte dan megabyte. 719 01:00:53,180 --> 01:00:55,020 Saya tumpukan bisa sangat besar. 720 01:00:55,020 --> 01:01:00,220 Tapi tumpukan itu sendiri harus dipecah menjadi halaman individual, 721 01:01:00,220 --> 01:01:09,010 yang jika kita melihat di sini mari kita mengatakan ini adalah RAM kami, 722 01:01:09,010 --> 01:01:16,600 jika saya memiliki 2 gigabyte RAM, ini adalah alamat 0 aktual seperti byte zeroth RAM saya, 723 01:01:16,600 --> 01:01:22,210 dan ini adalah 2 gigabyte sepanjang jalan ke sini. 724 01:01:22,210 --> 01:01:27,230 Jadi halaman ini mungkin sesuai dengan blok ini di sini. 725 01:01:27,230 --> 01:01:29,400 Halaman ini mungkin sesuai dengan blok ini di sini. 726 01:01:29,400 --> 01:01:31,560 Yang satu ini mungkin sesuai dengan yang satu ini di sini. 727 01:01:31,560 --> 01:01:35,540 Jadi sistem operasi bebas untuk menetapkan memori fisik 728 01:01:35,540 --> 01:01:39,320 untuk setiap halaman individu secara sewenang-wenang. 729 01:01:39,320 --> 01:01:46,180 Dan itu berarti bahwa jika perbatasan ini terjadi mengangkangkan array, 730 01:01:46,180 --> 01:01:50,070 array terjadi ditinggalkan ini dan kanan dari urutan halaman, 731 01:01:50,070 --> 01:01:54,460 maka array yang akan dibagi dalam memori fisik. 732 01:01:54,460 --> 01:01:59,280 Dan kemudian ketika Anda berhenti program, ketika proses berakhir, 733 01:01:59,280 --> 01:02:05,690 pemetaan ini bisa dihapus dan kemudian itu gratis untuk menggunakan blok kecil untuk hal-hal lainnya. 734 01:02:14,730 --> 01:02:17,410 Lebih banyak pertanyaan? 735 01:02:17,410 --> 01:02:19,960 [Mahasiswa] The aritmetik pointer. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 String yang mudah, tapi melihat sesuatu seperti ints, 737 01:02:28,410 --> 01:02:35,000 sehingga kembali ke int x [4]; 738 01:02:35,000 --> 01:02:41,810 Apakah ini adalah array atau apakah itu adalah pointer ke array malloced dari 4 bilangan bulat, 739 01:02:41,810 --> 01:02:47,060 itu akan diperlakukan dengan cara yang sama. 740 01:02:50,590 --> 01:02:53,340 [Mahasiswa] Jadi array di heap? 741 01:03:01,400 --> 01:03:05,270 [Bowden] Array tidak di heap. >> [Mahasiswa] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Jenis array cenderung di stack 743 01:03:08,320 --> 01:03:12,220 kecuali Anda menyatakan itu di - mengabaikan variabel global. Jangan menggunakan variabel global. 744 01:03:12,220 --> 01:03:16,280 Dalam fungsi saya katakan int x [4]; 745 01:03:16,280 --> 01:03:22,520 Ini akan membuat blok 4-bulat pada stack untuk array ini. 746 01:03:22,520 --> 01:03:26,960 Tapi ini malloc (4 * sizeof (int)); akan pergi di heap. 747 01:03:26,960 --> 01:03:31,870 Tapi setelah titik ini saya dapat menggunakan x dan p dalam cukup banyak cara yang sama, 748 01:03:31,870 --> 01:03:36,140 selain pengecualian saya katakan sebelumnya tentang Anda dapat menetapkan kembali p. 749 01:03:36,140 --> 01:03:40,960 Secara teknis, ukuran mereka agak berbeda, tapi itu sama sekali tidak relevan. 750 01:03:40,960 --> 01:03:43,310 Anda tidak pernah benar-benar menggunakan ukuran mereka. 751 01:03:48,020 --> 01:03:56,810 P saya bisa mengatakan p [3] = 2, atau x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Anda dapat menggunakannya dalam cara yang sama persis. 753 01:03:59,680 --> 01:04:01,570 Jadi pointer aritmatika sekarang - Ya. 754 01:04:01,570 --> 01:04:07,390 [Mahasiswa] Apakah Anda tidak perlu melakukan * p jika Anda memiliki tanda kurung? 755 01:04:07,390 --> 01:04:11,720 Tanda kurung adalah dereference implisit. Oke >>. 756 01:04:11,720 --> 01:04:20,200 Sebenarnya, juga apa yang Anda katakan dengan Anda bisa mendapatkan array multidimensi 757 01:04:20,200 --> 01:05:02,650 dengan pointer, apa yang dapat Anda lakukan adalah sesuatu seperti, katakanlah, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Saya hanya akan menulis semuanya pertama. 759 01:05:37,880 --> 01:05:41,020 Aku tidak ingin yang satu. 760 01:05:41,020 --> 01:05:42,550 Oke. 761 01:05:42,550 --> 01:05:48,910 Apa yang saya lakukan di sini adalah - Yang harus pp [i]. 762 01:05:48,910 --> 01:05:53,680 Jadi pp adalah pointer ke pointer. 763 01:05:53,680 --> 01:06:02,420 Anda mallocing pp untuk menunjuk ke array dari 5 int. 764 01:06:02,420 --> 01:06:10,950 Jadi dalam memori Anda miliki di pp stack 765 01:06:10,950 --> 01:06:20,150 Itu akan menunjuk ke array dari 5 blok yang semuanya sendiri pointer. 766 01:06:20,150 --> 01:06:28,210 Dan kemudian ketika saya malloc di sini, saya malloc bahwa masing-masing individu pointer 767 01:06:28,210 --> 01:06:32,080 harus menunjuk ke blok yang terpisah dari 4 byte di heap. 768 01:06:32,080 --> 01:06:35,870 Jadi ini menunjukkan 4 byte. 769 01:06:37,940 --> 01:06:40,660 Dan ini salah satu poin ke 4 byte yang berbeda. 770 01:06:40,660 --> 01:06:43,200 >> Dan mereka semua menunjuk ke mereka sendiri 4 byte. 771 01:06:43,200 --> 01:06:49,080 Ini memberi saya cara melakukan sesuatu multidimensi. 772 01:06:49,080 --> 01:06:58,030 Saya bisa mengatakan pp [3] [4], tetapi sekarang ini bukan hal yang sama dengan array multidimensi 773 01:06:58,030 --> 01:07:05,390 karena array multidimensi itu diterjemahkan [3] [4] menjadi satu offset ke array x. 774 01:07:05,390 --> 01:07:14,790 Ini p dereferences, mengakses indeks ketiga, maka dereferences bahwa 775 01:07:14,790 --> 01:07:20,790 dan akses - 4 akan valid - indeks kedua. 776 01:07:24,770 --> 01:07:31,430 Sedangkan ketika kita memiliki int x [3] [4] sebelumnya sebagai array multidimensi 777 01:07:31,430 --> 01:07:35,740 dan ketika Anda double braket itu benar-benar hanya dereference tunggal, 778 01:07:35,740 --> 01:07:40,490 Anda mengikuti pointer tunggal dan kemudian offset, 779 01:07:40,490 --> 01:07:42,850 ini benar-benar referensi 2D. 780 01:07:42,850 --> 01:07:45,840 Anda mengikuti 2 pointer terpisah. 781 01:07:45,840 --> 01:07:50,420 Jadi ini juga secara teknis memungkinkan Anda untuk memiliki array multidimensi 782 01:07:50,420 --> 01:07:53,550 di mana setiap array individu ukuran yang berbeda. 783 01:07:53,550 --> 01:07:58,000 Jadi saya pikir array multidimensi bergerigi adalah apa yang disebut 784 01:07:58,000 --> 01:08:01,870 karena benar-benar hal pertama yang bisa menunjukkan sesuatu yang memiliki 10 elemen, 785 01:08:01,870 --> 01:08:05,540 hal kedua bisa menunjukkan sesuatu yang memiliki 100 elemen. 786 01:08:05,540 --> 01:08:10,790 [Mahasiswa] Apakah ada batasan untuk jumlah pointer Anda dapat memiliki 787 01:08:10,790 --> 01:08:14,290 menunjuk ke pointer lain? >> No 788 01:08:14,290 --> 01:08:17,010 Anda dapat memiliki int ***** p. 789 01:08:18,050 --> 01:08:23,760 Kembali ke aritmatika pointer - >> [mahasiswa] Oh. >> Ya. 790 01:08:23,760 --> 01:08:35,649 [Mahasiswa] Jika saya memiliki int *** p dan kemudian saya melakukan dereferencing dan saya katakan * p sama dengan nilai ini, 791 01:08:35,649 --> 01:08:39,560 yang hanya akan melakukan 1 tingkat dereferencing? >> Ya. 792 01:08:39,560 --> 01:08:43,340 Jadi jika saya ingin mengakses hal yang pointer terakhir adalah menunjuk - 793 01:08:43,340 --> 01:08:46,210 Kemudian Anda melakukan p ***. Oke >>. 794 01:08:46,210 --> 01:08:54,080 Jadi ini adalah p poin ke 1 blok, menunjuk ke blok lain, menunjuk ke blok lain. 795 01:08:54,080 --> 01:09:02,010 Kemudian jika Anda lakukan * p = sesuatu yang lain, maka Anda mengubah ini 796 01:09:02,010 --> 01:09:13,640 sekarang menunjuk ke blok yang berbeda. Oke >>. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] Dan jika ini yang malloced, maka Anda sekarang telah bocor memori 798 01:09:17,649 --> 01:09:20,430 kecuali jika Anda kebetulan memiliki referensi yang berbeda dari 799 01:09:20,430 --> 01:09:25,270 karena Anda tidak bisa kembali ke orang-orang yang baru saja Anda membuang. 800 01:09:25,270 --> 01:09:29,550 Pointer aritmatika. 801 01:09:29,550 --> 01:09:36,310 int x [4], akan mengalokasikan sebuah array dari 4 bilangan bulat 802 01:09:36,310 --> 01:09:40,670 di mana x akan menunjuk ke awal array. 803 01:09:40,670 --> 01:09:50,420 Jadi ketika saya mengatakan sesuatu seperti x [1], saya ingin hal itu berarti pergi ke integer kedua dalam array, 804 01:09:50,420 --> 01:09:53,319 yang akan menjadi satu ini. 805 01:09:53,319 --> 01:10:04,190 Tapi sungguh, itu 4 byte ke array bilangan bulat karena ini membutuhkan 4 byte. 806 01:10:04,190 --> 01:10:08,470 Jadi offset 1 benar-benar berarti offset 1 807 01:10:08,470 --> 01:10:12,030 kali ukuran apapun jenis array. 808 01:10:12,030 --> 01:10:17,170 Ini adalah sebuah array bilangan bulat, sehingga tahu untuk melakukan 1 kali ukuran int ketika ingin mengimbangi. 809 01:10:17,170 --> 01:10:25,260 Sintaks lainnya. Ingatlah bahwa ini setara dengan * (x + 1); 810 01:10:25,260 --> 01:10:35,250 Ketika saya mengatakan pointer + 1, apa yang mengembalikan adalah alamat yang pointer yang menyimpan 811 01:10:35,250 --> 01:10:40,360 ditambah 1 kali ukuran dari jenis pointer. 812 01:10:40,360 --> 01:10:59,510 Jadi, jika x = ox100, maka x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 Dan Anda dapat penyalahgunaan ini dan mengatakan sesuatu seperti char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 dan sekarang c akan menjadi alamat yang sama sebagai x. 815 01:11:23,050 --> 01:11:26,040 c akan menjadi sama dengan ox100, 816 01:11:26,040 --> 01:11:31,490 tapi c + 1 akan menjadi sama dengan ox101 817 01:11:31,490 --> 01:11:38,030 sejak aritmatika pointer tergantung pada jenis pointer yang Anda menambah. 818 01:11:38,030 --> 01:11:45,390 Jadi c + 1, terlihat pada c, itu adalah pointer char, sehingga akan menambah 1 kali ukuran char, 819 01:11:45,390 --> 01:11:48,110 yang selalu akan menjadi 1, sehingga Anda mendapatkan 101, 820 01:11:48,110 --> 01:11:54,890 sedangkan jika saya melakukan x, yang juga masih 100, x + 1 akan menjadi 104. 821 01:11:56,660 --> 01:12:06,340 [Mahasiswa] Dapatkah Anda menggunakan c + + dalam rangka memajukan pointer Anda dengan 1? 822 01:12:06,340 --> 01:12:09,810 Ya, Anda bisa. 823 01:12:09,810 --> 01:12:16,180 Anda tidak bisa melakukan itu dengan x karena x adalah hanya simbol, itu adalah konstan, Anda tidak dapat mengubah x. 824 01:12:16,180 --> 01:12:22,610 >> Tapi c terjadi hanya menjadi pointer, sehingga c + + benar-benar berlaku dan akan increment 1. 825 01:12:22,610 --> 01:12:32,440 Jika c adalah hanya sebuah * int, maka c + + akan 104. 826 01:12:32,440 --> 01:12:41,250 + + Tidak aritmetik pointer seperti c + 1 akan melakukan aritmetik pointer. 827 01:12:43,000 --> 01:12:48,870 Ini sebenarnya bagaimana banyak hal-hal seperti gabungan semacam - 828 01:12:49,670 --> 01:12:55,710 Alih-alih membuat salinan dari hal-hal, Anda malah bisa lewat - 829 01:12:55,710 --> 01:13:02,400 Seperti jika saya ingin melewati setengah dari array - mari kita menghapus beberapa ini. 830 01:13:04,770 --> 01:13:10,520 Katakanlah saya ingin lulus sisi array ke dalam fungsi. 831 01:13:10,520 --> 01:13:12,700 Apa yang akan saya lolos ke fungsi itu? 832 01:13:12,700 --> 01:13:17,050 Jika saya lulus x, saya lewat alamat ini. 833 01:13:17,050 --> 01:13:23,780 Tapi aku ingin melewati ini alamat tertentu. Jadi apa yang harus saya lulus? 834 01:13:23,780 --> 01:13:26,590 [Mahasiswa] Pointer + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Jadi x + 2. Ya. 836 01:13:29,350 --> 01:13:31,620 Itu akan menjadi alamat ini. 837 01:13:31,620 --> 01:13:42,810 Anda juga akan sangat sering melihatnya sebagai x [2] dan kemudian alamat itu. 838 01:13:42,810 --> 01:13:47,850 Jadi, Anda perlu untuk mengambil alamat karena braket adalah dereference implisit. 839 01:13:47,850 --> 01:13:53,250 x [2] mengacu pada nilai yang ada di kotak ini, dan kemudian Anda ingin alamat kotak itu, 840 01:13:53,250 --> 01:13:56,850 sehingga Anda katakan & x [2]. 841 01:13:56,850 --> 01:14:02,880 Jadi itulah bagaimana sesuatu di semacam gabungan di mana Anda ingin melewati setengah daftar untuk sesuatu 842 01:14:02,880 --> 01:14:08,790 Anda benar-benar hanya lulus & x [2], dan sekarang sejauh panggilan rekursif yang bersangkutan, 843 01:14:08,790 --> 01:14:12,510 array baru saya mulai ada. 844 01:14:12,510 --> 01:14:15,130 Terakhir menit pertanyaan. 845 01:14:15,130 --> 01:14:20,050 [Mahasiswa] Jika kita tidak menempatkan sebuah ampersand atau - apa yang disebut? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Mahasiswa] Star. >> Teknis, operator dereference, tapi - >> [mahasiswa] dereference. 847 01:14:23,200 --> 01:14:29,310 >> Jika kita tidak menempatkan bintang atau ampersand, apa yang terjadi jika saya hanya mengatakan y = x dan x adalah pointer? 848 01:14:29,310 --> 01:14:34,620 Apa jenis y? >> [Mahasiswa] Aku hanya akan mengatakan pointer itu 2. 849 01:14:34,620 --> 01:14:38,270 Jadi jika Anda hanya mengatakan y = x, sekarang x dan titik y ke hal yang sama. >> [Mahasiswa] Point untuk hal yang sama. 850 01:14:38,270 --> 01:14:45,180 Dan jika x adalah pointer int? >> Ini akan mengeluh karena Anda tidak dapat menetapkan pointer. 851 01:14:45,180 --> 01:14:46,540 [Mahasiswa] Oke. 852 01:14:46,540 --> 01:14:51,860 Ingat bahwa pointer, meskipun kita menarik mereka sebagai anak panah, 853 01:14:51,860 --> 01:15:02,010 benar-benar semua toko mereka - int * x - x benar-benar menyimpan semua adalah sesuatu seperti ox100, 854 01:15:02,010 --> 01:15:06,490 yang kita terjadi untuk mewakili sebagai menunjuk ke blok disimpan pada 100. 855 01:15:06,490 --> 01:15:19,660 Jadi ketika saya mengatakan int * y = x; Aku hanya menyalin ox100 ke y, 856 01:15:19,660 --> 01:15:24,630 yang kita hanya akan mewakili sebagai y, juga menunjuk ke ox100. 857 01:15:24,630 --> 01:15:39,810 Dan jika saya mengatakan int i = (int) x; maka saya akan menyimpan apapun nilai ox100 adalah 858 01:15:39,810 --> 01:15:45,100 di dalamnya, tapi sekarang itu akan ditafsirkan sebagai integer bukan pointer. 859 01:15:45,100 --> 01:15:49,310 Tapi Anda perlu pemain atau yang lain itu akan mengeluh. 860 01:15:49,310 --> 01:15:53,300 [Mahasiswa] Jadi maksudmu untuk membuang - 861 01:15:53,300 --> 01:16:00,290 Apakah akan pengecoran int int x atau casting y? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Apa? 863 01:16:03,700 --> 01:16:07,690 [Mahasiswa] Oke. Setelah tanda kurung yang ada akan menjadi x atau ay sana? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] Entah. x dan y adalah setara. >> [Mahasiswa] Oke. 865 01:16:11,500 --> 01:16:14,390 Karena mereka berdua pointer. >> Ya. 866 01:16:14,390 --> 01:16:21,050 [Mahasiswa] Jadi akan menyimpan 100 heksadesimal dalam bentuk integer? >> [Bowden] Ya. 867 01:16:21,050 --> 01:16:23,620 Tapi tidak nilai apa pun menunjuk ke. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Ya. >> [Mahasiswa] Jadi hanya alamat dalam bentuk integer. Oke. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Jika Anda ingin untuk beberapa alasan aneh, 870 01:16:34,720 --> 01:16:38,900 Anda secara eksklusif bisa berurusan dengan pointer dan tidak pernah berurusan dengan bilangan bulat 871 01:16:38,900 --> 01:16:49,240 dan hanya menjadi seperti int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Kemudian Anda akan mendapatkan benar-benar bingung sekali aritmatika pointer mulai terjadi. 873 01:16:53,000 --> 01:16:56,570 Jadi angka-angka yang mereka menyimpan yang berarti. 874 01:16:56,570 --> 01:16:58,940 Ini hanya bagaimana Anda akhirnya menginterpretasikannya. 875 01:16:58,940 --> 01:17:02,920 Jadi aku bebas untuk menyalin ox100 dari * int ke int, 876 01:17:02,920 --> 01:17:07,790 dan aku bebas untuk menetapkan - Anda mungkin akan dimarahi karena tidak pengecoran - 877 01:17:07,790 --> 01:17:18,160 Aku bebas untuk menetapkan sesuatu seperti (int *) ox1234 ke dalam * int sewenang-wenang. 878 01:17:18,160 --> 01:17:25,480 Jadi ox123 sama validnya alamat memori seperti & y. 879 01:17:25,480 --> 01:17:32,060 & Y terjadi kembali sesuatu yang cukup banyak ox123. 880 01:17:32,060 --> 01:17:35,430 [Mahasiswa] Apakah itu cara yang sangat keren untuk pergi dari heksadesimal ke bentuk desimal, 881 01:17:35,430 --> 01:17:39,230 seperti jika Anda memiliki pointer dan Anda melemparkan sebagai int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Anda dapat benar-benar hanya mencetak menggunakan seperti printf. 883 01:17:44,860 --> 01:17:50,300 Katakanlah saya memiliki int y = 100. 884 01:17:50,300 --> 01:18:02,700 Jadi printf (% d \ n - seperti yang Anda sudah harus tahu - cetak bahwa sebagai integer, x%. 885 01:18:02,700 --> 01:18:05,190 Kami hanya akan mencetaknya sebagai heksadesimal. 886 01:18:05,190 --> 01:18:10,760 Jadi pointer tidak disimpan sebagai heksadesimal, 887 01:18:10,760 --> 01:18:12,960 dan integer tidak disimpan sebagai desimal. 888 01:18:12,960 --> 01:18:14,700 Semuanya disimpan sebagai biner. 889 01:18:14,700 --> 01:18:17,950 Hanya saja kita cenderung untuk menunjukkan pointer sebagai heksadesimal 890 01:18:17,950 --> 01:18:23,260 karena kita memikirkan hal-hal dalam 4-byte blok, 891 01:18:23,260 --> 01:18:25,390 dan alamat memori cenderung akrab. 892 01:18:25,390 --> 01:18:28,890 Kita seperti, jika dimulai dengan bf, maka akan terjadi pada stack. 893 01:18:28,890 --> 01:18:35,560 Jadi itu hanya penafsiran kita pointer sebagai heksadesimal. 894 01:18:35,560 --> 01:18:39,200 Oke. Setiap pertanyaan terakhir? 895 01:18:39,200 --> 01:18:41,700 >> Aku akan berada di sini sebentar setelah jika Anda memiliki apa-apa lagi. 896 01:18:41,700 --> 01:18:46,070 Dan itulah akhir dari itu. 897 01:18:46,070 --> 01:18:48,360 >> [Mahasiswa] Yay! [Tepuk tangan] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]