1 00:00:00,000 --> 00:00:02,440 [Powered by Google Translate] [Payo] 2 00:00:02,440 --> 00:00:05,000 [Rob Bowden] [Harvard University] 3 00:00:05,000 --> 00:00:07,360 [Ito ay CS50] [CS50.TV] 4 00:00:07,360 --> 00:00:08,820 >> Natin makipag-usap tungkol sa mga payo. 5 00:00:08,820 --> 00:00:13,710 Hanggang ngayon, laging kami lang tinutukoy sa mga bagay sa memory tahasang sa pamamagitan ng pangalan. 6 00:00:13,710 --> 00:00:22,610 Namin ang sinabi n int = 42; at pagkatapos kapag gusto naming gamitin ang variable n, 7 00:00:22,610 --> 00:00:30,640 namin lamang tumawag ito sa pamamagitan ng pangalan namin ibinigay ito sa pamamagitan ng pagsusulat ng isang bagay tulad ng n * 2. 8 00:00:30,640 --> 00:00:34,790 Ngunit variable na dapat nakatira sa isang lugar sa memorya. 9 00:00:34,790 --> 00:00:37,790 Kapag nais mong gamitin ang halaga na ay kasalukuyang naka-imbak sa loob n, 10 00:00:37,790 --> 00:00:40,730 o i-update ang halaga na n ay may hawak, 11 00:00:40,730 --> 00:00:44,180 ang iyong programa ay kailangang malaman kung saan sa memory upang tumingin para sa n. 12 00:00:44,180 --> 00:00:48,320 Saan sa memory ng variable buhay ay tinatawag na ang address nito. 13 00:00:48,320 --> 00:00:49,940 Ito ay tulad ng isang address ng bahay. 14 00:00:49,940 --> 00:00:53,080 Maaari kong makahanap ng bahay ng isang tao hangga't alam ko ang kanilang home address, 15 00:00:53,080 --> 00:00:58,110 at isang computer program ay maaaring makahanap ng isang variable hangga't alam nito memory address. 16 00:00:58,110 --> 00:01:02,660 Anong mga payo magbigay ay isang paraan ng direktang pagharap sa mga address na ito ng memorya. 17 00:01:02,660 --> 00:01:06,860 >> Isang maraming ng kapangyarihan sa C ay mula sa pagiging magagawang upang manipulahin ang memory tulad nito. 18 00:01:06,860 --> 00:01:09,960 Ngunit may dakilang kapangyarihan pagdating mahusay na responsibilidad. 19 00:01:09,960 --> 00:01:14,670 Pointer ay maaaring gamitin dangerously sapat na ng maraming mga wika ng programming 20 00:01:14,670 --> 00:01:16,460 itago ang kabuuan ng mga payo. 21 00:01:16,460 --> 00:01:19,440 Kaya, kung bakit ang C bigyan kami ng payo pagkatapos? 22 00:01:19,440 --> 00:01:22,680 Tulad ng alam mo, argumento sa isang function C 23 00:01:22,680 --> 00:01:25,370 palaging kinopya sa mga parameter ng function na. 24 00:01:25,370 --> 00:01:33,260 Kaya, ang pagtawag ng isang bagay tulad makipagpalitan sa ilang mga variable x at y 25 00:01:33,260 --> 00:01:38,840 hindi maaaring Interchange ang mga halaga ng x at y sa pagtawag sa function na, 26 00:01:38,840 --> 00:01:40,810 kahit na maaaring maging madaling-magamit na. 27 00:01:40,810 --> 00:01:46,430 Bilang makikita namin makita mamaya, muling pagsusulat makipagpalitan sa tumagal ng mga payo sa lokasyon na nangangailangan na swapped 28 00:01:46,430 --> 00:01:49,690 ay nagbibigay-daan sa ito upang makaapekto sa variable nito tumatawag. 29 00:01:49,690 --> 00:01:54,150 >> Lakad natin sa pamamagitan ng ganap na tapat Halimbawa ng kung ano ang payo ay maaaring gawin. 30 00:01:54,150 --> 00:02:15,550 Sabihin nating mayroon kaming int n = 4; at int * pointer_to_n = & n. 31 00:02:15,550 --> 00:02:18,990 Whoa! Isang bit ng bagong syntax upang masakop ang. 32 00:02:18,990 --> 00:02:22,600 Una, sabihin bigyang-kahulugan ang mga ito at n. 33 00:02:22,600 --> 00:02:27,260 Tandaan na ang lahat sa memory ang ilang address. 34 00:02:27,260 --> 00:02:30,800 Ampersand ay tinatawag na ang "address ng" operator. 35 00:02:30,800 --> 00:02:36,470 Kaya, & n ay tumutukoy sa address sa memorya kung saan n ay naka-imbak. 36 00:02:36,470 --> 00:02:41,560 Ngayon, kami ay pag-iimbak sa address na ito sa isang bagong variable, pointer_to_n. 37 00:02:41,560 --> 00:02:43,870 Ano ang uri ng mga bagong variable na ito? 38 00:02:43,870 --> 00:02:47,410 Asterisk ay isang bahagi ng uri ng variable, 39 00:02:47,410 --> 00:02:49,880 at kami na basahin ang mga uri ng int *. 40 00:02:49,880 --> 00:02:56,500 Int * ay nangangahulugan na pointer_to_n ay isang variable na nag-iimbak ng address ng isang integer. 41 00:02:56,500 --> 00:03:02,970 Alam namin na & n ay isang int * dahil n ay isang integer, at kami ay paglalaan ng address ng n. 42 00:03:02,970 --> 00:03:06,660 Int * ay isang halimbawa ng isang uri ng pointer. 43 00:03:06,660 --> 00:03:10,150 Sa lalong madaling simulan mo ang nakakakita ng mga asterisk sa uri, 44 00:03:10,150 --> 00:03:11,950 alam mo na ikaw ay pagharap sa mga payo. 45 00:03:11,950 --> 00:03:16,520 Lamang tulad ng maaari naming ipinapahayag sa isang variable ng int x at magpasinda y, 46 00:03:16,520 --> 00:03:20,410 maaari naming sabihin int * z at magpasinda * w. 47 00:03:20,410 --> 00:03:25,190 Int * at magpasinda * bago lang na uri para sa amin upang gamitin. 48 00:03:25,190 --> 00:03:29,430 Ang lokasyon ng * pumunta saanman bago ang pangalan ng variable. 49 00:03:29,430 --> 00:03:34,730 Kaya, ang parehong int * pointer_to_n - na may * na susunod sa int, mayroon kaming dito - 50 00:03:34,730 --> 00:03:45,210 at int * pointer_to_n gamit ang * sa tabi pointer_to_n wasto. 51 00:03:45,210 --> 00:03:56,470 Ngunit dito, makikita ko bang ilagay ang * sa tabi ng int. 52 00:03:56,470 --> 00:04:00,600 Hindi mahalaga kung saan gusto mo, maging pare-pareho lamang. 53 00:04:00,600 --> 00:04:02,810 >> Natin gumuhit ng diagram para sa. 54 00:04:02,810 --> 00:04:07,590 Muna namin ang variable n, na makikita namin gumuhit bilang isang maliit na kahon ng memorya. 55 00:04:07,590 --> 00:04:15,400 Para sa halimbawang ito, sabihin natin na ang kahon na ito ay matatagpuan sa address 100. 56 00:04:15,400 --> 00:04:18,820 Loob ng ang kahon na ito, kami ay ang pag-iimbak ang halaga 4. 57 00:04:18,820 --> 00:04:23,730 Ngayon, mayroon kaming isang bagong variable, pointer_to_n. 58 00:04:23,730 --> 00:04:27,030 Ito ay may sarili nitong box sa memorya, 59 00:04:27,030 --> 00:04:32,900 na gagamitin namin sabihin sa address 200. 60 00:04:32,900 --> 00:04:37,220 Loob ng ang kahon na ito, kami ay itinatago ang address ng n, 61 00:04:37,220 --> 00:04:39,890 kung saan bago namin sinabi ay 100. 62 00:04:39,890 --> 00:04:44,710 Madalas sa diagram, makikita mo ito ipinapakita bilang isang literal na arrow 63 00:04:44,710 --> 00:04:48,730 umaalis sa pointer_to_n box na tumuturo sa box na nag-iimbak n. 64 00:04:48,730 --> 00:04:54,620 Ngayon, kung ano ang maaari naming aktwal na gawin sa pointer_to_n? 65 00:04:54,620 --> 00:05:10,400 Well, kung sinasabi namin ang isang bagay tulad ng * pointer_to_n = 8, ito ay isang ibang paggamit para sa asterisk 66 00:05:10,400 --> 00:05:14,830 na ganap na nakahiwalay mula sa paggamit ng asterisk sa deklarasyon ng variable 67 00:05:14,830 --> 00:05:16,790 ng isang uri ng pointer. 68 00:05:16,790 --> 00:05:21,130 Dito, ang asterisk ay tinatawag na dereference operator. 69 00:05:21,130 --> 00:05:26,860 Sa aming diagram, ano * pointer_to_n = 8 paraan, 70 00:05:26,860 --> 00:05:32,220 pumunta sa ang kahon na naglalaman pointer_to_n, sundin ang mga arrow, 71 00:05:32,220 --> 00:05:38,160 at pagkatapos ay italaga sa ang kahon sa dulo ng arrow ang halaga 8. 72 00:05:38,160 --> 00:05:45,960 Nangangahulugan ito na matapos ang linyang ito, kung sinusubukan naming gamitin n ito ang halaga 8. 73 00:05:45,960 --> 00:05:51,600 'Pointer' Ang salita ay ginagamit sa maraming mga iba't ibang konteksto. 74 00:05:51,600 --> 00:05:54,380 Dito, susubukan naming maging pare-pareho. 75 00:05:54,380 --> 00:05:58,330 Isang pointer uri ay isang bagay tulad ng int *. 76 00:05:58,330 --> 00:06:04,630 Sa video na ito, ang isang pointer ay ay lamang ginagamit sa ibig sabihin ng isang halaga sa isang uri ng pointer, 77 00:06:04,630 --> 00:06:08,180 tulad pointer_to_n na may * uri int. 78 00:06:08,180 --> 00:06:15,140 Kahit saan ginamit namin lamang sabihin ng n, maaari namin ngayon sa halip sabihin * pointer_to_n, 79 00:06:15,140 --> 00:06:18,020 at ang lahat ay gagana lamang pati na rin. 80 00:06:18,020 --> 00:06:21,120 >> Lakad natin sa pamamagitan ng isa pang simpleng halimbawa. 81 00:06:21,120 --> 00:06:50,390 Sabihin nating mayroon kaming int n = 14; int * pointer = &n; n + +, at (* pointer) + +. 82 00:06:50,390 --> 00:06:59,830 Ang unang linya ay lumilikha ng isang bagong kahon sa memory na may label n. 83 00:06:59,830 --> 00:07:05,400 Oras na ito, hindi namin label ang kahon na may isang tahasang address, ngunit pa rin ito ay may isa. 84 00:07:05,400 --> 00:07:11,810 Sa loob ng kahon sa, kami ay itinatago ang bilang 14. 85 00:07:11,810 --> 00:07:22,290 Ang susunod na linya ay lumilikha ng isang pangalawang kahon na may label pointer. 86 00:07:22,290 --> 00:07:27,210 At sa loob ng kahon na ito, kami ay pag-iimbak ng isang pointer sa kahon na may label n. 87 00:07:27,210 --> 00:07:33,170 Kaya, sabihin gumuhit ang arrow mula sa pointer sa n. 88 00:07:33,170 --> 00:07:37,790 Ngayon, n + + palugit ang halaga sa kahon na may label na n, 89 00:07:37,790 --> 00:07:45,420 kaya namin pumunta 14-15. 90 00:07:45,420 --> 00:07:53,330 Panghuli, (* pointer) + + napupunta sa kahon na may label ng pointer, 91 00:07:53,330 --> 00:08:02,660 dereferences halaga sa kahon, na nangangahulugan na sundin ang mga arrow sa kung saan ito POINTS, 92 00:08:02,660 --> 00:08:11,690 at palugit ang halaga na nakaimbak doon, kaya kami 15-16. 93 00:08:11,690 --> 00:08:13,480 At na ito. 94 00:08:13,480 --> 00:08:18,480 N ngayon iniimbak ang numero 16 matapos dalawang beses na incremented - 95 00:08:18,480 --> 00:08:25,050 sabay-sabay nang direkta sa pamamagitan ng paggamit ng ang mga variable na n pangalan, at ang iba pa sa pamamagitan ng pointer_to_n. 96 00:08:25,050 --> 00:08:33,360 >> Mabilis na pagsusulit. Ano sa tingin ninyo ang ibig sabihin nito kung sinusubukan kong sabihin na ang isang bagay tulad && n? 97 00:08:33,360 --> 00:08:41,350 Well, ipaalam sa muling isulat ito bilang & (& n) na accomplishes ang parehong bagay. 98 00:08:41,350 --> 00:08:47,030 Ang (& n) nagbabalik ang address ng variable n sa memory. 99 00:08:47,030 --> 00:08:53,110 Ngunit pagkatapos pagkatapos panlabas ampersand ay sinusubukan upang ibalik ang address ng address. 100 00:08:53,110 --> 00:08:56,600 Iyon ay tulad ng sinusubukang gawin & 2. 101 00:08:56,600 --> 00:09:00,550 Hindi ito magkaroon ng kahulugan upang makuha ang address ng ilan lang bilang 102 00:09:00,550 --> 00:09:03,260 dahil hindi ito naka-imbak sa memorya. 103 00:09:03,260 --> 00:09:07,090 Paggamit ng dalawang ampersand sa isang hilera ay hindi kailanman ang karapatan na ideya. 104 00:09:07,090 --> 00:09:28,960 Ngunit ngayon, ano ang ibig sabihin kung sinusubukan kong sabihin na ang int ** double_pointer = & pointer? 105 00:09:28,960 --> 00:09:40,750 Ngayon, ako ang paglikha ng isang bagong kahon na may label na double_pointer, 106 00:09:40,750 --> 00:09:44,590 at sa loob ng kahon na ako sa pag-iimbak ng address ng pointer, 107 00:09:44,590 --> 00:09:50,810 na nangangahulugan ko gumuhit ng isang arrow mula sa double_pointer kahon sa kahon ng pointer. 108 00:09:50,810 --> 00:09:56,640 Pansinin ang uri ng double_pointer, isang int **. 109 00:09:56,640 --> 00:10:03,700 N ay isang integer, pointer na naka-imbak na ang address ng n, at kaya may * uri int. 110 00:10:03,700 --> 00:10:10,550 Ngayon, nag-iimbak ng double_pointer ang address ng pointer, kaya ito ay may uri int **. 111 00:10:10,550 --> 00:10:15,070 >> Kaya, kung ano ang sa tingin namin Nangangahulugan itong - 112 00:10:15,070 --> 00:10:24,490 ** Double_pointer = 23? 113 00:10:24,490 --> 00:10:28,630 Pansinin na ako ngayon dereferencing dalawang beses. 114 00:10:28,630 --> 00:10:32,030 Sundin lang ang mga box-at-arrow diagram na namin ang set up. 115 00:10:32,030 --> 00:10:36,400 Una, pumunta kami sa kahon na may label na double_pointer. 116 00:10:36,400 --> 00:10:40,550 Ang unang * ibig sabihin sundin ang mga arrow sa isang beses. 117 00:10:40,550 --> 00:10:44,110 Ngayon, hindi namin sa kahon na may label na pointer. 118 00:10:44,110 --> 00:10:49,940 Ang ikalawang bituin na sundin ang mga arrow muli, 119 00:10:49,940 --> 00:10:58,230 at ngayon hindi namin sa kahon na may label na n, at namin itakda ang halaga ng ang kahon na ito sa 23. 120 00:10:58,230 --> 00:11:05,940 Pansinin na ang dereference at address ng 'operator mga inverses ng isa't isa. 121 00:11:05,940 --> 00:11:16,990 Ito ay nagbibigay-daan sa akin upang gawin ang isang bagay tulad ng * & * & n = 42. 122 00:11:16,990 --> 00:11:22,550 Habang ito gumagana, hindi mo dapat gawin ang isang bagay tulad nito sa kasanayan. 123 00:11:22,550 --> 00:11:24,840 Ano kami aktwal na ginagawa dito? 124 00:11:24,840 --> 00:11:28,700 Ang unang ampersand grabs ang address ng variable n. 125 00:11:28,700 --> 00:11:34,660 Pagkatapos, mayroon kaming dereference operator, na nangangahulugan na namin ay pagpunta sa address na iyon sa memorya, 126 00:11:34,660 --> 00:11:36,910 kaya hindi namin pabalik sa n. 127 00:11:36,910 --> 00:11:40,910 Ngayon, grab namin ang mga address ng n muli at agad dereference, 128 00:11:40,910 --> 00:11:50,780 kaya hindi namin pabalik sa n at tindahan 42. 129 00:11:50,780 --> 00:11:55,490 Kaya, ang bawat pares ng * & lang magkakansela out. 130 00:11:55,490 --> 00:11:59,980 >> May ay isang espesyal na pointer na tinatawag na ang null pointer. 131 00:11:59,980 --> 00:12:03,140 Ito ay isang pointer na hindi namin dapat dereference. 132 00:12:03,140 --> 00:12:07,130 Tulad pointer ay mahalaga sapagkat ito ay nagbibigay sa amin ng isang paraan upang makilala sa pagitan ng 133 00:12:07,130 --> 00:12:10,220 isang pointer na dapat at hindi dapat dereferenced. 134 00:12:10,220 --> 00:12:13,050 Kung sinubukan mong mag-dereference null pointer, 135 00:12:13,050 --> 00:12:17,150 karaniwang iyong programa ay pag-crash ng may isang segmentation fault, 136 00:12:17,150 --> 00:12:19,210 kung saan maaaring nakakita ka bago. 137 00:12:19,210 --> 00:12:30,490 Kaya, sabihin nating mayroon kaming ang code int * x = null; * x = 4. 138 00:12:30,490 --> 00:12:36,190 Sa halimbawang ito, maaaring mukhang halata na namin ang paggawa ng isang bagay masamang, 139 00:12:36,190 --> 00:12:40,650 ngunit tandaan na null maaaring talagang maging isang halaga na ibinalik mula sa isang tawag sa isang function 140 00:12:40,650 --> 00:12:45,930 tulad ng malloc, kung malloc hindi maglaan ang memory na hiniling ng user. 141 00:12:45,930 --> 00:12:50,200 Para sa kadahilanang ito, kung sa halip namin itakda ang halaga ng x mula sa isang tawag sa malloc, 142 00:12:50,200 --> 00:13:12,050 sa int * x = malloc (sizeof (int)), pagkatapos ay dapat namin laging tahasang suriin 143 00:13:12,050 --> 00:13:15,280 upang makita kung null ay ibinalik. 144 00:13:15,280 --> 00:13:43,250 Kung (x == null); / / uhoh! return; pa ang maaari naming magpatuloy at sabihin * x = 4. 145 00:13:43,250 --> 00:13:47,780 >> Kaya, muli, kung bakit dapat namin gamitin ang mga payo? 146 00:13:47,780 --> 00:13:51,910 Tingnan natin sa isang halimbawa ng isang programa na kung saan kailangan naming gamitin ang mga payo - 147 00:13:51,910 --> 00:13:54,110 isang simpleng makipagpalitan ng function na. 148 00:13:54,110 --> 00:14:08,270 Ipagpalagay natin na mayroon akong dalawang integer, int x = 4, at int y = 15; 149 00:14:08,270 --> 00:14:21,220 at gusto kong magsulat ng isang function na tinatawag na makipagpalitan na maaari kong gamitin tulad ng sa gayon: makipagpalitan ng (x, y). 150 00:14:21,220 --> 00:14:28,270 Matapos ang linyang ito, ang mga halaga sa loob ng variable x ay dapat na 15, 151 00:14:28,270 --> 00:14:32,360 at ang halaga sa loob variable y dapat na 4. 152 00:14:32,360 --> 00:14:36,510 Ang mga halaga sa loob ng x at y ay swapped. 153 00:14:36,510 --> 00:14:53,040 Walang mga payo, maaari naming subukan ang isang bagay tulad ng walang bisa makipagpalitan (int a, int b); 154 00:14:53,040 --> 00:15:09,750 int tmp = b; b = isang; a = tmp. 155 00:15:09,750 --> 00:15:12,960 Ngunit, huwag mong mapansin ang problema na ito? 156 00:15:12,960 --> 00:15:19,000 Tandaan na ang halaga na naka-imbak sa variable lamang ng isang kopya ng ang halaga ng x, 157 00:15:19,000 --> 00:15:22,000 at ang halaga sa b kinopya mula sa y. 158 00:15:22,000 --> 00:15:28,000 Anumang pagbabago na ginawa sa isang at b ay hindi makikita sa x at y. 159 00:15:28,000 --> 00:15:32,050 Kaya, habang ang halaga ng isang at b ay tama swapped, 160 00:15:32,050 --> 00:15:35,810 x at y na hindi nagbago sa lahat. 161 00:15:35,810 --> 00:15:38,480 Ngayon, sabihin baguhin ang makipagpalitan ng function na upang na ang argumento 162 00:15:38,480 --> 00:15:42,180 mga payo sa mga variable na ito ay dapat swap, i kaya: 163 00:15:42,180 --> 00:15:56,880 makipagpalitan ng void (int * a, int * b); int tmp = * b; * b = * a; * a = tmp. 164 00:15:56,880 --> 00:16:00,140 Tandaan na ang swaps argumento ngayon payo, 165 00:16:00,140 --> 00:16:05,670 at kaya kailangan namin upang pumasa ang address ng x at y sa tawag sa swap, i kaya: 166 00:16:05,670 --> 00:16:15,280 swap (& x, at y). 167 00:16:15,280 --> 00:16:20,520 Ito ngayon tama swaps ang mga halaga ng x at y. 168 00:16:20,520 --> 00:16:24,310 >> Natin gumuhit ng kahon-at-arrow diagram upang makita kung bakit ito gumagana. 169 00:16:24,310 --> 00:16:28,520 Magsisimula kami sa aming dalawang mga kahon sa memory, x at y. 170 00:16:28,520 --> 00:16:35,780 Sa loob ng box para sa x ay ang bilang 4, at sa loob ng box para sa y mayroon kaming 15. 171 00:16:35,780 --> 00:16:41,200 Ngayon, sa loob ng pagtawag sa function na makipagpalitan ng, mayroon kaming dalawang mas maraming mga kahon 172 00:16:41,200 --> 00:16:45,140 para sa argumento at b; 173 00:16:45,140 --> 00:16:50,960 ng mga puntos sa ang kahon para sa x, at b puntos sa box para sa y. 174 00:16:50,960 --> 00:16:58,070 Ang isang bagong kahon ay nilikha para sa variable na tmp, 175 00:16:58,070 --> 00:17:01,470 at sa loob nito imbak ng namin ang resulta ng dereferencing b, 176 00:17:01,470 --> 00:17:04,980 na nangangahulugan na 'sundin ang mga arrow mula sa kahon na may label na b.' 177 00:17:04,980 --> 00:17:09,880 Kaya, iniimbak namin ang 15 sa loob ng tmp. 178 00:17:09,880 --> 00:17:20,560 Pagkatapos, sundin namin ang arrow sa b at mag-store dito ang resulta ng dereferencing ng, 179 00:17:20,560 --> 00:17:24,569 na ang halaga 4. 180 00:17:24,569 --> 00:17:35,590 Panghuli, sundin namin ang mga arrow sa at tindahan kung ano ang kasalukuyang loob ng tmp, na 15. 181 00:17:35,590 --> 00:17:42,440 Pansinin na ang mga kahon na may label na x at y tama swapped halaga. 182 00:17:42,440 --> 00:17:46,290 >> Sa sandaling aming matuto nang higit pa tungkol sa malloc at dynamic memory pamamahala, 183 00:17:46,290 --> 00:17:49,610 makikita namin makita na wala kaming pagpipilian ngunit upang gamitin ang mga payo. 184 00:17:49,610 --> 00:17:52,690 Naglalakad sa pamamagitan ng kahon-at-arrow diagram para sa anumang programa 185 00:17:52,690 --> 00:17:55,980 ay maaaring makatulong sa iyo na malaman kung ano ang programa ay talagang ginagawa. 186 00:17:55,980 --> 00:17:59,680 >> Ang pangalan ko ay Rob Bowden, at ito ay CS50. 187 00:18:00,000 --> 00:18:02,500 [CS50.TV] 188 00:18:02,500 --> 00:18:06,070 >> Ito ay isang ibang paggamit para sa asterisk - bleah, mapoot ko ang salitang iyon. 189 00:18:06,070 --> 00:18:13,960 Kahit saan ginamit namin lamang sabihin ng n, maaari naming ngayon sabihin pointer_to_n - walang Hindi mai ka - * pointer_to_n.