[Powered by Google Translate] [Частка 4 - больш камфортнай]
[Rob Боуден - Гарвардскі універсітэт]
[Гэта CS50. - CS50.TV]
У нас ёсць тэст заўтра, у выпадку, калі вы, хлопцы, не ведаю, што.
Гэта ў асноўным усё, што вы маглі бачыць у класе або павiнны былi бачыць у сваім класе.
Гэта ўключае ў сябе паказальнікі, нават калі яны зусім нядаўна тэма.
Вы павінны па крайняй меры, зразумець высокага ўзроўню з іх.
Усё, што было перайшлі ў клас вы павінны разумець, для віктарыны.
Так што калі ў вас ёсць пытанні па іх, вы можаце задаць іх цяпер.
Але гэта будзе вельмі студэнта пад кіраўніцтвам сесіі, дзе вы, хлопцы, задаваць пытанні,
так што спадзяюся, людзям ёсць пытанні.
У каго-небудзь ёсць пытанні?
Так. >> [Студэнт] Ці можаце вы перайсці на паказальнікі зноў?
Я пайду за паказальнікамі.
Усе вашыя зменныя абавязкова жыць у памяці,
але звычайна вы не хвалюйцеся пра гэта, і вы проста кажаце х + 2, у + 3
і кампілятар будзе высветліць, дзе жывуць рэчы для вас.
Калі вы маеце справу з паказальнікамі, зараз вы відавочна з дапамогай гэтых адрасоў памяці.
Такім чынам, адной зменнай будзе толькі тады, калі жыць па адным адрасе ў любы момант часу.
Калі мы хочам абвясціць паказальнік, то, што тып будзе выглядаць?
>> Я хачу абвясціць паказальнік р. Што ж тыпу выглядаюць?
[Студэнт] Int * р. >> Так. Так Int * р.
А як зрабіць, каб яна паказвала на х? >> [Студэнт] Ampersand.
[Боуден] Так амперсанда літаральна называецца адрас аператара.
Таму, калі я кажу, і х ён становіцца адрас памяці зменнай х.
Так што зараз у мяне ёсць паказальнік р, і ў любым месцы ў маім кодзе я магу выкарыстоўваць * р
ці я мог бы выкарыстаць х, і гэта будзе адно і тое ж.
(* Р). Што гэта робіш? Што азначае, што зорка на ўвазе?
[Студэнт] Гэта азначае значэнне ў гэтай кропцы. >> Так.
Так, калі мы глядзім на яго, ён можа быць вельмі карысна, каб выцягнуць дыяграм
дзе гэта маленькая скрыначка памяці для х, у якім ёсць значэнне 4,
Затым у нас ёсць маленькая скрыначка памяці для р,
і так з пункту х, так што мы малюем стрэлку ад р х.
Таму калі мы гаворым * р мы гаворым пайсці ў акно, р.
Зорка прытрымлівайцеся за стрэлкай, а затым рабіць усё, што вы хочаце з гэтай скрынцы прама там.
Таму я магу сказаць * р = 7, і што пойдзе на скрыню, які з'яўляецца х і змены, якія да 7.
Ці я мог бы сказаць Int г = * р * 2; Гэта зман, таму што гэта зорка, зорка.
Адна зорка разнаймення р, іншая зорка памнажэннем на 2.
Звярніце ўвагу, я мог бы з такім жа поспехам замянілі * р з х.
Вы можаце выкарыстоўваць іх такім жа чынам.
А потым на мяне можа быць з пункту на цалкам новую рэч.
Я магу толькі сказаць, р = &z;
Так што цяпер P больш не паказвае на х; ён паказвае на г.
І ў любы час я * р гэта так жа, як рабіў г.
Такім чынам, карысная рэч пра гэта як толькі мы пачынаем атрымліваць па функцыях.
>> Гэта свайго роду бескарысныя абвясціць паказальнік, які паказвае на тое,
а затым вы проста разнаймення яго
калі вы маглі б выкарыстоўваць арыгінальны зменную з самага пачатку.
Але калі вы атрымліваеце ў функцыі - так скажам, у нас ёсць некаторыя функцыі, унутр Фу,
, Якая прымае паказальнік і проста робіць * р = 6;
Як мы бачылі раней з падпампоўкі, вы не можаце зрабіць эфектыўны абмен і асобныя функцыі
ад проста праходзілі цэлыя таму што ўсё ў C заўсёды праходзяць па значэнні.
Нават тады, калі вы перадаеце паказальнік вы перадаеце па значэнні.
Проста так атрымалася, што гэтыя значэнні адрасоў памяці.
Таму калі я кажу Foo (р); я перадаю паказальнік ў функцыі Foo
, А затым Foo робіць * р = 6;
Такім чынам, унутры гэтай функцыі, * р-ранейшаму эквівалентна х,
але я не магу выкарыстоўваць х ўнутры гэтай функцыі, таму што гэта не вобласцю ў гэтай функцыі.
Так * р = 6 з'яўляецца адзіным спосабам я магу атрымаць доступ з лакальнай зменнай іншую функцыю.
Ці, добра, паказальнікі з'яўляюцца адзіным спосабам я магу атрымаць доступ да лакальнай зменнай з іншай функцыі.
[Студэнт] Дапушчальны, вы хацелі вяртаць паказальнік. Як менавіта вы гэта зрабілі?
[Боуден] Вяртае паказальнік, як у нешта накшталт Int у = 3; вяртанне & Y? >> [Студэнт] Так.
[Боуден] Добра. Вы ніколі не павінны гэта рабіць. Гэта дрэнна.
Я думаю, што я бачыў у гэтыя лекцыі слайды вы пачалі бачыць усю гэтую схему памяці
дзе тут у вас ёсць памяць адрас 0
і тут у вас ёсць адрас памяці, 4 гігабайтамі або ад 2 да 32.
Такім чынам, то ў вас ёсць некаторыя рэчы і некаторыя рэчы, а затым у вас ёсць свой стэк
і ў вас ёсць ваша куча, якую вы толькі пачалі вывучэнне, расце.
[Студэнт] не з'яўляецца кучай над стэкам?
>> Так. Куча знаходзіцца на вяршыні, ці не так? >> [Студэнт] Ну, ён паставіў 0 на вяршыні.
[Студэнт] О, ён паставіў 0 на вяршыні. >> [Студэнт] О, усё ў парадку.
Адмова ад адказнасці: Anywhere з CS50 вы ўбачыце яго такім чынам. >> [Студэнт] Добра.
Гэта толькі, што, калі вы ўпершыню убачыўшы стэкі,
падабаецца, калі вы думаеце пра стэку вы думаеце кладкі рэчаў адзін на аднаго.
Такім чынам, мы, як правіла, каб перагарнуць гэтую вакол так стэк расце ўверх, як гэта звычайна стэк
замест таго, каб стэк вісіць ўніз. >> [Студэнт] Не кучы тэхнічна расці занадта, праўда?
Гэта залежыць ад таго, што вы разумееце пад расці.
Стэка і кучы заўсёды растуць у процілеглым кірунку.
Стэк заўсёды растуць у тым сэнсе, што яно расце
да больш высокім адрасах памяці, і куча расце ўніз
у тым, што ён расце ў бок меншых адрасоў памяці.
Такім чынам, верхні роўны 0, а ніжні з'яўляецца высокая адрасоў памяці.
Яны абодва расце, толькі ў процілеглых кірунках.
[Студэнт] Я проста меў на ўвазе, што, паколькі вы сказалі, паклаў стэк на дно
таму што здаецца больш інтуітыўным, паколькі для стэка для запуску ў верхняй частцы кучы,
куча знаходзіцца на вяршыні самога таксама, так што that's - >> Так.
Вы таксама думаць пра кучы, як растуць і больш, але ў стэку больш.
Такім чынам, стэк з'яўляецца той, які мы як бы хочуць паказаць растуць.
Але куды ні глянь у адваротным выпадку пакажа адрас 0 у верхнім
і самы высокі адрас памяці ў ніжняй, так што гэта звычайны выгляд памяці.
>> У вас ёсць пытанне?
[Студэнт] Ці можаце вы распавесці нам больш пра кучы?
Так. Я вярнуся да гэтага ў секунду.
Па-першае, вяртаючыся да вяртання і чаму ў дрэнная рэч,
ў стэку ў вас ёсць куча кадраў стэка, якія прадстаўляюць усе функцыі
якія былі названыя.
Такім чынам, ігнаруючы папярэднія рэчы, у верхняй частцы стэка заўсёды будзе галоўнай функцыяй
так як гэта першая функцыя, якая выклікаецца.
А потым, калі вы тэлефануеце іншую функцыю, стэк будзе расці ўніз.
Так што, калі я называю некаторыя функцыі, Foo, і ён атрымлівае уласны фрэйм ​​стэка,
ён можа выклікаць некаторыя функцыі, бар, ён атрымлівае уласны фрэйм ​​стэка.
І бар можа быць рэкурсіўнай, і гэта можа выклікаць саму сябе,
і так, што другі выклік бары збіраецца атрымаць свой фрэйм ​​стэка.
І таму тое, што адбываецца ў гэтых кадраў стэка з'яўляюцца ўсе лакальныя зменныя
і ўсе аргументы функцыі, што -
Любыя рэчы, якія маюць лакальную вобласць дзеяння гэтай функцыі перайдзіце ў гэтых кадраў стэка.
Такім чынам, гэта азначае, што, калі я сказаў нешта накшталт бара з'яўляецца функцыяй,
Я проста хачу, каб абвясціць цэлае, а затым вяртае паказальнік на гэта лік.
Дык дзе ж у жывяце?
[Студэнт] у жыве ў бары. >> [Боуден] Так.
Дзесьці ў гэтым маленькім квадраце памяці квадратных Литтлер, які мае ў ў ім.
Калі я вярнуся, і ў, я вяртаю паказальнік на гэты невялікі блок памяці.
Але потым, калі функцыя вяртаецца, яго стэк атрымлівае стэка.
І менавіта таму яна называецца стэкам.
Гэта як структуры дадзеных стэка, калі вы ведаеце, што гэта такое.
Ці нават як стэк латкоў заўсёды, напрыклад,
Асноўнымі збіраецца пайсці на дно, то першая функцыя вы тэлефануеце збіраецца пайсці на вяршыні, што,
і вы не можаце вярнуцца на галоўную, пакуль не вернецеся з усіх функцый, якія былі закліканы
, Якія былі размешчаны на ім.
>> [Студэнт] Так што калі вы рабілі вярнуцца і ў, што кошт можа быць зменена без папярэдняга паведамлення.
Так, it's - >> [студэнт] Гэта можа быць перазапісаная. >> Так.
Гэта цалкам - Калі вы паспрабуеце -
Гэта таксама было б Int бар *, таму што гэта вяртае паказальнік,
так што яго вяртанне тыпу Int *.
Калі вы паспрабуеце выкарыстоўваць вяртаецца значэнне гэтай функцыі, гэта нявызначаны паводзіны
таму што паказальнік паказвае на дрэнную памяць. >> [Студэнт] Добра.
Так што, калі, напрыклад, вы заявілі Int * у = таНос (SizeOf (INT))?
Так-то лепш. Так.
[Студэнт] Мы казалі пра тое, калі мы перацягнуць рэчы ў нашы кошыка
яны на самой справе не сціраюцца, мы проста губляюць свае паказальнікі.
Таму ў дадзеным выпадку мы на самай справе выдаліць значэнне або гэта яшчэ там, у памяці?
Па большай частцы, гэта будзе яшчэ будзе там.
Але, дапусцім, мы, здараецца, называюць некаторыя іншыя функцыі, Баз.
База збіраецца атрымаць свой фрэйм ​​стэка тут.
Гэта будзе перазапісваць ўсе гэтыя рэчы,
, А затым, калі вы пазней паспрабаваць выкарыстоўваць паказальнік, які вы атрымалі раней,
гэта не будзе тое ж значэнне.
Гэта будзе змяніліся толькі таму, што вы выклікалі функцыю Баз.
[Студэнт] Але калі б мы не, мы б да гэтага часу атрымаць 3?
[Боуден] Па ўсёй верагоднасці, вы б.
Але вы не можаце спадзявацца на гэта. C проста кажа нявызначаны паводзіны.
>> [Студэнт] О, гэта так. Добра.
Такім чынам, калі вы хочаце вярнуць паказальнік, гэта дзе таНос прыходзіць ў выкарыстанні.
Я пішу на самай справе проста вярнуць таНос (3 * SizeOf (INT)).
Мы пройдземся па таНос яшчэ ў секунду, але ідэя таНос гэта ўсё лакальныя зменныя
заўсёды ідуць у стэк.
Нічога, што malloced ідзе па кучы, і ён будзе вечна і заўсёды быць у кучы
пакуль вы відавочна вызваліць яго.
Такім чынам, гэта азначае, што калі вы таНос нешта, яна збіраецца выжыць пасля вяртання з функцыі.
[Студэнт] Ці будзе яна выжыць пасля таго, як праграма спыняецца? >> Не.
Добра, так што гэта будзе там, пакуль праграма цалкам не зрабіў працу. >> Так.
Мы можам пайсці на дэталі таго, што адбываецца, калі праграма спыняецца.
Вам можа спатрэбіцца, каб нагадаць мне, але гэта асобная рэч цалкам.
[Студэнт] Так таНос стварае паказальнік? >> Так.
Malloc - >> [студэнт] Я думаю, што таНос пазначае блок памяці, які можна выкарыстоўваць у якасці паказальніка.
[Боуден] Я хачу, каб схема зноў. >> [Студэнт] Такім чынам, гэтая функцыя працуе, праўда?
[Студэнт] Так, таНос пазначае блок памяці, які можна выкарыстоўваць,
а затым вяртае адрас першага блока гэтай памяці.
>> [Боуден] Так. Такім чынам, калі вы таНос, вы захоп некаторых блок памяці
што ў цяперашні час у кучы.
Калі куча занадта мала, то куча за ўсё будзе расці, і яно расце ў гэтым кірунку.
Так скажам, куча занадта малая.
Тады гаворка ідзе пра расці трохі, і вяртае паказальнік на гэты блок толькі расла.
Калі Вы бясплатна рэчы, вы робіце больш месца ў кучы,
так, то пазней патэлефанаваць у таНос можа выкарыстоўваць гэтую памяць, што раней вы ўжо вызваленыя.
Галоўнае пра таНос і бясплатна, што яна дае вам поўны кантроль
на працягу тэрміну службы гэтых блокаў памяці.
Глабальныя зменныя заўсёды жывая.
Лакальныя зменныя жывыя ў межах сваёй кампетэнцыі.
Як толькі вы ідзяце міма фігурнай дужкай, лакальныя зменныя мёртвыя.
Malloced памяць жывая, калі вы хочаце, каб ён быў жывы
, А затым вызваляецца, калі вы сказаць, што гэта павінен быць вызвалены.
Тыя, на самай справе з'яўляюцца толькі 3 тыпаў памяці, на самай справе.
Там у аўтаматычнае кіраванне памяццю, якая з'яўляецца стэк.
Усё адбываецца аўтаматычна.
Калі вы кажаце Int х, памяці вылучаецца для внутр х.
Пры х выходзіць з вобласці бачнасці, памяць будзе утылізаваны для х.
Тады ёсць дынамічнае кіраванне памяццю, што і таНос ёсць,
які з'яўляецца, калі ў вас ёсць кантроль.
Вы дынамічна вырашыць, калі памяць павінна і не павінна быць выдзелена.
А тут яшчэ статычныя, які проста азначае, што ён жыве вечна,
што і глабальныя зменныя.
Яны проста заўсёды ў памяці.
>> Пытанні?
[Студэнт] Ці можаце вы вызначыць блок толькі з дапамогай фігурных дужак
але не таго, каб мець, калі заяву або заяву падчас ці нешта ў гэтым родзе?
Вы можаце вызначыць блок, як у функцыі, але гэта не мае фігурныя дужкі таксама.
[Студэнт] Такім чынам, вы не можаце проста як выпадковыя пара фігурных дужак у кодзе
, Якія маюць лакальныя зменныя? >> Так, можна.
Усярэдзіне Int бары мы маглі б мець {INT у = 3;}.
Гэта павінна быць тут.
Але гэта цалкам вызначае сферу Int у.
Пасля таго, што другі фігурнай дужкай, у не можа быць выкарыстана больш.
Вы амаль ніколі не робяць гэтага, хоць.
Вяртаючыся да таго, што адбываецца, калі праграма сканчаецца,
там, здаецца, зман / палова хлусня, што мы даем для таго, каб проста зрабіць рэчы прасцей.
Мы кажам вам, што, калі вы вылучыць памяць
Вы выдзяленні некаторых кавалак аператыўнай памяці для гэтай зменнай.
Але вы сапраўды не дакранаючыся непасрэдна RAM усё ў вашых праграмах.
Калі вы думаеце пра гэта, як я намаляваў -
А на самай справе, калі вы праходзіце ў GDB вы ўбачыце, што тое ж самае.
Незалежна ад таго, колькі разоў вы запусціце праграму або якой праграмай вы працуеце,
Стэк заўсёды збіраецца пачаць -
Вы заўсёды ўбачыце зменныя вакол адрас нешта oxbffff.
Гэта, як правіла, дзесьці ў гэтым рэгіёне.
Але як 2 праграмы магчыма мець паказальнікі на тую ж памяць?
[Студэнт] Там некаторыя адвольныя абазначэння, дзе oxbfff павінна быць на RAM
якія сапраўды могуць знаходзіцца ў розных месцах, у залежнасці ад таго, калі функцыя была выклікана.
Так. Гэты тэрмін з'яўляецца віртуальнай памяці.
Ідэя складаецца ў тым, што кожны працэс, кожная праграма, якая працуе на вашым кампутары
мае сваю ўласную - выкажам здагадку, 32 біт - цалкам незалежная адраснай прасторы.
Гэта адрасная прастора.
Ён мае свой уласны цалкам незалежнымі 4 гігабайта ў выкарыстанні.
>> Так што калі вы запусціце 2 праграмы адначасова, гэтая праграма бачыць 4 гігабайта да сябе,
гэтая праграма бачыць 4 гігабайта да сябе,
і немагчыма для гэтай праграмы разыменовать паказальнік
і ў выніку памяці з гэтай праграмы.
І тое, што віртуальная памяць з'яўляецца адлюстраваннем з адраснай прасторы працэсу
фактычных рэчаў на памяць.
Так што да вашай аперацыйнай сістэме ведаць, што,
эй, калі гэты паказальнік хлопец разыменовывает oxbfff, што на самой справе азначае
што ён хоча байт RAM 1000,
а калі гэта oxbfff праграмы разыменовывает, што ён сапраўды хоча байт RAM 10000.
Яны могуць быць калі заўгодна далёка адзін ад аднаго.
Гэта дакладна нават рэчы ў адным адраснай прасторы працэсу.
Так як ён бачыць усё 4 гігабайта да сябе, але, скажам -
[Студэнт] ці кожны працэс -
Скажам, у вас ёсць кампутар з 4 гігабайтамі аператыўнай памяці.
Ці мае кожны працэс ўбачыць цэлых 4 гігабайта? >> Так.
Але 4 гігабайта ён бачыць гэта хлусня.
Гэта проста ён думае, што ўсё гэта мае памяці, таму што ён не ведае, і любы іншы працэс існуе.
Ён будзе выкарыстоўваць толькі столькі памяці, колькі на самай справе трэба.
Аперацыйная сістэма не дасць RAM ў гэты працэс
калі ён не выкарыстоўвае памяць ва ўсёй гэтай галіне.
Гэта не збіраюся даць яму памяць для гэтага рэгіёну.
Але ідэя ў тым, што - я спрабую думаць - я не магу думаць аб аналогія.
Аналогіі цяжка.
Адзін з пытанняў, віртуальнай памяці, ці адна з рэчаў, гэта рашэнне
з'яўляецца тое, што працэсы павінны быць у поўным няведаньні адзін ад аднаго.
І такім чынам, вы можаце напісаць любую праграму, якая проста разыменовывает любой паказальнік,
хацеў проста напісаць праграму, якая кажа * (ox1234),
і гэта разнаймення адрас памяці 1234.
>> Але гэта да аперацыйнай сістэмы, каб затым перавесці тое, што 1234 сродкі.
Так, калі 1234 апынецца сапраўдны адрас памяці для гэтага працэсу,
як ён у стэк або нешта, то гэта будзе вяртаць значэнне дадзенага адрасы памяці
Што тычыцца працэсу ведае.
Але калі 1234 не з'яўляецца сапраўдным адрасам, як гэта адбываецца на зямлю
У некаторых маленькі кавалачак памяці тут, што выходзіць за межы стэка і кучы
і вы сапраўды не выкарысталі гэта, то што, калі вы атрымліваеце нешта накшталт сегментацыі
таму што ты дакранаешся памяці, якія вы не павінны дакранацца.
Гэта таксама дакладна -
32-бітная сістэма, 32 біт азначае, што ў вас ёсць 32 біта для вызначэння адрасы памяці.
Вось чаму паказальнікаў 8 байт, паколькі 32 біт 8 байт - ці 4 байт.
Паказальнікі 4 байт.
Таму, калі вы бачыце паказальнік, як oxbfffff, гэта значыць -
У любой гэтай праграмы вы можаце проста пабудаваць любы адвольны паказальнік,
у любым месцы ад Ох0 Ох 8 f's - FFFFFFFF.
[Студэнт] Хіба вы не кажаце, што яны 4 байта? >> Так.
[Студэнт] Тады кожны байт будзе - >> [Боуден] шаснаццатковай.
Шаснаццаткавыя - 5, 6, 7, 8. Так паказальнікаў вы будзеце заўсёды бачыць у шаснаццатковым выглядзе.
Гэта проста, як мы классифицируем паказальнікаў.
Кожныя 2 лічбы шаснаццатковай 1 байт.
Так што гэта будзе 8 шаснаццатковых лічбаў на 4 байта.
Такім чынам, кожны паказальнік на 32-бітнай сістэме будзе 4 байта,
Гэта азначае, што ў вашым працэсе можна пабудаваць любы адвольны 4 байта
і зрабіць паказальнік з яго,
Гэта азначае, што, наколькі ён ведае, ён можа звярнуцца цэлая 2 да 32 байт памяці.
Нават калі гэта на самай справе не маюць доступу да гэтай,
нават калі ваш кампутар мае толькі 512 мегабайт, ён думае, што ён мае шмат памяці.
І аперацыйная сістэма дастаткова разумная, што яна будзе толькі вылучыць тое, што вам сапраўды трэба.
Гэта не проста ісці, ой, новы працэс: 4 канцэртаў.
>> Так. >> [Студэнт] Што бык значыць? Чаму вы пішаце?
Гэта проста сімвал шаснаццатковай.
Калі вы бачыце нумар пачынаецца з быка, паслядоўныя рэчы шаснаццатковае.
[Студэнт] Вы былі растлумачыць, што адбываецца, калі праграма сканчаецца. >> Так.
Што адбываецца, калі праграма сканчаецца ўяўляе сабой аперацыйную сістэму
проста сцірае адлюстраванняў, што яна мае для гэтых адрасоў, вось і ўсё.
У якасці аперацыйнай сістэмы цяпер можна проста даць, што памяць у іншай праграме выкарыстоўваць.
[Студэнт] Добра.
Такім чынам, калі вы вылучыць нешта ў кучы або ў стэку або глабальныя зменныя або што-небудзь,
усе яны проста знікаюць, як толькі праграма заканчваецца
, Паколькі аперацыйная сістэма зараз можа даць, што памяць для любога іншага працэсу.
[Студэнт] Нават калі Ёсць, верагодна, яшчэ значэння напісаны на? >> Так.
Значэння, верагодна, усё яшчэ там.
Гэта проста, што гэта будзе цяжка атрымаць на іх.
Гэта значна цяжэй атрымаць на іх, чым гэта, каб дабрацца да аддаленых файлаў
таму што выдалены файл выгляду сядзіць там на працягу доўгага часу і жорсткага дыска нашмат больш.
Такім чынам, ён збіраецца перапісаць розных частках памяці
перш чым гэта адбудзецца, каб замяніць кавалак памяці, што файл, які выкарыстоўваецца каб быць у.
Але асноўнай памяці, RAM, вы цыкла праз шмат хутчэй,
так што гэта будзе вельмі хутка будуць перапішуцца.
Пытанні на гэтую ці нешта яшчэ?
[Студэнт] У мяне ёсць пытанні аб іншай тэме. >> Добра.
Хто-небудзь ёсць пытанні па гэтай нагоды?
>> Добра. Розныя тэмы. >> [Студэнт] Добра.
Я ішоў праз некаторыя практычныя тэсты,
і ў адной з іх ён казаў пра SizeOf
і значэнне, якое яна вяртае або розных тыпаў зменных. >> Так.
І ён сказаў, што абодва Int і доўга, як вяртанне 4, так што яны абодва 4 байта.
Ці ёсць розніца паміж Int і доўга, ці гэта адно і тое ж?
Так, ёсць розніца.
C стандарт -
Я, верагодна, будзе беспарадак.
C стандарт проста падабаецца тое, што C ёсць афіцыйная дакументацыя C.
Гэта тое, што ён кажа.
Такім чынам, C стандартная проста кажа, што знак будзе вечна і заўсёды будзе 1 байт.
Усё, пасля гэтага - кароткі заўсёды проста вызначыць як больш або роўная знак.
Гэта можа быць строга больш, але не станоўча.
Int проста вызначаецца як больш або роўна кароткі.
І доўга проста вызначаецца як большая ці роўнае Int.
І доўга-доўга, больш або роўна доўга.
Так што адзінае, C стандарт вызначае адносны парадак ва ўсім.
Фактычны аб'ём памяці, што рэчы займаюць, як правіла, да рэалізацыі,
але ён вельмі добра вызначана ў гэтай кропцы. >> [Студэнт] Добра.
Такім чынам, шорты амаль заўсёды будзе 2 байта.
Ints амаль заўсёды будзе 4 байт.
Доўгія доўгія, амаль заўсёды будзе 8 байт.
І марыць, гэта залежыць ад таго, ці выкарыстоўваецца 32-бітныя або 64-бітныя сістэмы.
Так доўга будзе адпавядаць тыпу сістэмы.
Калі вы выкарыстоўваеце 32-разрадную сістэму, як Appliance, гэта будзе 4 байт.
Калі вы выкарыстоўваеце 64-разрадную, як шмат апошніх кампутарах, гэта будзе 8 байт.
>> Ints амаль заўсёды 4 байта ў гэтай кропцы.
Доўгія доўгія, амаль заўсёды 8 байт.
У мінулым цэлыя выкарыстаны толькі быць 2 байта.
Але звярніце ўвагу, што гэта цалкам задавальняе ўсе гэтыя адносіны больш і роўная.
Да тых часоў, выдатна дазволена быць такога ж памеру, як цэлае,
і гэта таксама дазволена мець той жа памер, як доўга доўга.
І так ужо здараецца, што ў 99,999% сістэм, будзе роўная
альбо Int або доўгі доўга. Гэта залежыць толькі ад 32-бітнай або 64-бітнай. >> [Студэнт] Добра.
У паплаўкі, якім дзесятковай кропкі, пазначанай у плане біт?
Накшталт як бінарны? >> Так.
Вам не трэба ведаць, што для CS50.
Вы нават не пазнаеце, што ў 61.
Вы не пазнаеце, што сапраўды ў любы курс.
Гэта проста паданне.
Я забыўся дакладнае надзелы няшмат.
Ідэя з якая плавае кропкай з'яўляецца тое, што вы вылучыць пэўную колькасць біт для прадстаўлення -
У прынцыпе, усё ў навуковай натацыі.
Такім чынам, вы вылучыць пэўную колькасць біт для прадстаўлення самога ліку, як і 1.2345.
Я ніколі не могуць прадстаўляць ліку з больш чым 5 лічбаў.
Пасля гэтага вы таксама вылучыць пэўную колькасць бітаў, так што ён імкнецца быць падобным на
Вы можаце ісці толькі да вызначанага ліку, як і самы вялікі паказчык вы можаце мець,
і вы можаце ісці толькі да пэўнага паказчыка,
як гэта найменшы паказчык вы можаце мець.
>> Я не памятаю дакладна біты шляху прызначаюцца на ўсе гэтыя каштоўнасці,
але пэўную колькасць бітаў прысвечаны 1.2345,
іншы пэўную колькасць бітаў прызначаныя для экспаненты,
і гэта толькі можна ўявіць паказчыкам пэўнага памеру.
[Студэнт] і двайны? Хіба што, як і падоўжаныя паплавок? >> Так.
Гэта тое ж самае, як паплавок толькі цяпер вы выкарыстоўваеце 8 байт замест 4 байт.
Зараз вы зможаце выкарыстоўваць 9 лічбаў або 10 лічбаў,
і гэта будзе ў стане пайсці да 300 замест 100. >> [Студэнт] Добра.
І паплаўкі таксама 4 байта. >> Так.
Ну, зноў жа, гэта, верагодна, залежыць у цэлым на агульную рэалізацыю,
але паплаўкі 4 байта, двухмесныя з'яўляюцца 8.
Парны называюцца падвойнымі, таму што яны ў два разы паплаўкоў.
[Студэнт] Добра. І ёсць падвойнае падвойвае? >> Ёсць не так.
Я думаю - >> [студэнт] Як доўга сумуе? >> Так. Не думаю. Так.
[Студэнт] На цесцю ў мінулым годзе там было пытанне аб асноўнай функцыі
таго, каб быць часткай вашай праграмы.
Адказ быў, што яна не павінна быць часткай вашай праграмы.
У якой сітуацыі? Гэта тое, што я бачыў.
[Боуден] Здаецца - >> [студэнт] Якая сітуацыя?
Ці ёсць у вас праблемы? >> [Студэнт] Так, я магу дакладна пацягніце яго ўверх.
Гэта не павінны быць тэхнічна, але ў асноўным гэта будзе.
[Студэнт] Я бачыў аднаго на другі год.
Гэта было падобна Дакладна або няма: сапраўды - >> О, з файлам.?
. [Студэнт] Любое З файл павінен мець - [як кажа адразу - неразборліва]
Добра. Дык вось асобна.
>> . C файл, проста павінен змяшчаць функцый.
Вы можаце скампіляваць файл у машынны код, двайковы, што заўгодна,
без яго выкананым яшчэ няма.
Сапраўдны выкананы файл павінен мець асноўную функцыю.
Вы можаце напісаць 100 функцый у 1 файл, але не асноўная
, А затым скампіляваць, што аж да двайковы,
Затым вы пішаце іншы файл, які мае толькі галоўнай, але яна выклікае кучу гэтых функцый
У гэты двайковы файл тут.
І таму, калі вы робіце выкананы файл, вось што робіць кампаноўнік
яно спалучае ў сабе гэтыя 2 двайковых файлаў у выкананы файл.
Так. У файле не павінна быць асноўнай функцыяй на ўсіх.
І на вялікіх базах кода вы ўбачыце тысячы. Файлы з і 1 галоўны файл.
Яшчэ пытанні?
[Студэнт] Існаваў яшчэ адно пытанне.
Ён сказаў, зрабіць гэта кампілятар. Праўда ці Хлусня?
І адказ быў ілжывым, і я зразумеў, чаму гэта не так, як Clang.
Але тое, што мы называем зрабіць, калі гэта не так?
Зрабіць гэта ў асноўным проста - я бачу менавіта тое, што ён гэта называе.
Але гэта толькі выконвае каманды.
Зрабіць.
Я магу пацягнуць гэта. Так.
О, так. Пераканайцеся таксама, што робіць.
Гэта сведчыць аб мэты марку ўтыліта для аўтаматычнага вызначэння
якія часткі вялікай праграмы павінны быць перакампіляваны
і выдае каманды для іх перакампілявання.
Вы можаце зрабіць файлы, якія з'яўляюцца абсалютна велізарна.
Зрабіць глядзіць на штампы часу файлаў і, як мы ўжо казалі,
Вы можаце сабраць асобныя файлы ўніз, і гэта не пакуль не дойдзе да кампаноўнік
што яны сабралі ў выкананы файл.
Так што калі ў вас ёсць 10 розных файлаў, і вы ўнесці змены ў 1 з іх,
тое, што робіць збіраецца зрабіць, гэта проста перакампілявання, што 1 файл
, А затым паўторна звязаць усе разам.
Але значна тупей, чым гэта.
Гэта да вас, каб цалкам вызначыць, што гэта тое, што ён павінен рабіць.
Гэта па змаўчанні мае здольнасць распазнаваць гэты матэрыял штамп часу,
але вы можаце напісаць зрабіць файл нічога рабіць.
Вы можаце напісаць зрабіць файл, так што, калі вы ўводзіце зрабіць гэта толькі кампакт-дыскі ў іншы каталог.
Я расчараваныя, таму што я трэка ўнутры ўсе мае Appliance
а потым прагледзець PDF з Mac.
>> Так што я іду ў Finder, і я магу сапраўды ідзяце, падлучыцца да сервера,
і сервер падлучыцца да маё Appliance, а затым я адкрываю PDF
, Які атрымлівае складзены LaTeX.
Але мяне не будзе, бо, таму што кожны раз, калі мне трэба, каб абнавіць PDF,
Мне прыйшлося скапіяваць яго ў пэўны каталог, што ён можа атрымаць доступ да
і гэта рабілася раздражняе.
Так што замест гэтага я напісаў зрабіць файл, які вы павінны вызначыць, як ён робіць рэчы.
Як вы робіце ў гэты PDF LaTeX.
Гэтак жа, як і любы іншы файл маркі - ці я думаю, вы яшчэ не бачылі марку файлаў,
але ў нас ёсць у прыбор файл глабальных маркі, якія проста кажа:
калі вы компилируете файл C, выкарыстоўвайце Clang.
І вось тут, у маёй зрабіць файл, што я раблю я кажу,
Гэты файл вы збіраецеся хочаце сабраць з PDF LaTeX.
І такім чынам, гэта PDF LaTeX, што робіць кампіляцыю.
Зрабіць гэта не кампіляцыя. Гэта проста выканання наступных каманд у паслядоўнасці я паказаў.
Такім чынам, яна працуе PDF LaTeX, ён капіюе яго ў каталог, я хачу, каб быць скапіяваная,
гэта кампакт-дыскаў у каталогу і робіць іншыя рэчы,
але ўсё яна робіць, гэта прызнаюць пры змене файла,
і калі ён змяняецца, то яна будзе працаваць камандамі, якія ён павінен выканаць
Пры змене файла. >> [Студэнт] Добра.
Я не ведаю, дзе глабальныя файлы зрабіць для мяне, каб праверыць яго.
Іншыя пытанні? Усё, пачынаючы ад мінулых тэстаў? Любы паказальнік рэчы?
Ёсць тонкія рэчы з паказальнікамі, як -
Я не збіраюся быць у стане знайсці пытанне віктарыны на ім -
але, як і такога роду рэчы.
Пераканайцеся, што вы разумееце, што, калі я кажу Int * х * У -
Гэта не зусім тут нічога, я думаю.
Але, як і * х * у, тыя 2 зменныя, якія знаходзяцца на стэку.
Калі я кажу, х = таНос (SizeOf (INT)), х-ранейшаму зменнай у стэк,
таНос некаторы блок больш у кучу, і мы мае пункту х да кучы.
>> Так что-то ў стэк паказвае на кучу.
Кожны раз, калі вы таНос што-небудзь, вы непазбежна захоўваць яго ўнутры мышы.
Так што паказальнік на стэк, malloced блока ў кучы.
Многія людзі блытаюць і кажуць Int * х = таНос; х у кучу.
Кол-х Што паказвае на гэта ў кучу.
х сама знаходзіцца ў стэку, калі па якіх-небудзь прычынах вы х глабальнай зменнай,
У гэтым выпадку ён аказваецца ў іншай вобласці памяці.
Такім чынам адсочваць гэтыя скрынкі і стрелочные дыяграмы з'яўляюцца даволі агульнымі для віктарыны.
Або, калі гэта не тэст на 0, гэта будзе на тэст 1.
Вы павінны ведаць усё гэта, крокі ў складанні
так як вы павінны былі адказаць на пытанні на іх. Так.
[Студэнт] Ці можам мы пайсці на гэтыя крокі - >> Вядома.
Перад крокаў і складанне нас ёсць папярэдняя апрацоўка,
кампіляцыі, зборкі і кампаноўкі.
Папярэдняя апрацоўка. Што ж гэта зрабіць?
Гэта самы просты крок у - добра, не падабаецца -
гэта не значыць, павінна быць відавочным, але гэта самы просты крок.
Вы, хлопцы маглі рэалізаваць сябе. Так.
[Студэнт] Вазьміце тое, што ў вас ёсць у вашай ўключае ў сябе, як гэта і капіюе, а затым і вызначае.
Ён шукае рэчы, як # # ўключаюць у сябе і вызначыць,
і ён проста капіюе і ўстаўляе тое, што тыя на самай справе азначае.
Таму, калі вы кажаце # ўключыць cs50.h, препроцессор капіявання і ўстаўкі cs50.h
у гэтай лініі.
Калі вы кажаце: # вызначыць х роўным 4, препроцессор праходзіць праз усю праграму
і замяняе усе асобнікі х з 4.
Такім чынам, препроцессор прымае правільны файл C і выдае правільны файл C
, Дзе рэчы былі скапіяваныя.
Так што цяпер кампіляцыі. Што ж гэта зрабіць?
[Студэнт] Гэта ідзе ад C у двайковы фармат.
>> [Боуден] Гэта не прайсці ўвесь шлях у двайковы фармат.
[Студэнт] у машынны код то? >> Гэта не машынны код.
[Студэнт] Асамблеі? >> Асамблеі.
Гэта ідзе ў Асамблеі перш чым ён ідзе ўсю дарогу ў код C,
і большасць моў зрабіць нешта накшталт гэтага.
Выберыце любы мова высокага ўзроўню, і калі вы збіраецеся кампіляваць яго,
гэта, верагодна, сабраць у кроках.
Спачатку ён збіраецца скласці Python ў C, то гэта будзе для кампіляцыі C Асамблеі,
, А затым Асамблея збіраецца атрымаць перавод у двойкавую.
Такім чынам, складанне збіраецца вывесці яго з C Асамблеі.
Слова кампіляцыі звычайна азначае прывядзенне яго ад больш высокага ўзроўню
у ніжняй мова праграмавання высокага ўзроўню.
Так што гэта толькі крок у кампіляцыі, дзе вы пачынаеце з мовы высокага ўзроўню
і ў канчатковым выніку ў мову нізкага ўзроўню, і таму крок называецца кампіляцыяй.
[Студэнт] У час кампіляцыі, давайце скажам, што вы зрабілі # ўключыць cs50.h.
Ці будзе перакампіляваць кампілятар cs50.h, як і функцыі, якія там,
, І перавесці гэта ў ассемблерный код, а таксама,
ці гэта скапіяваць і ўставіць тое, што было папярэдне сход?
cs50.h будзе амаль ніколі не аказваюцца ў Асамблеі.
Рэчы, як прататыпы функцый і рэчаў для вас быць асцярожнымі.
Гэта гарантуе, што кампілятар можа праверыць такія рэчы, як вы выклікаеце функцыі
з правам тыпы вяртання і правільныя аргументы і іншае.
>> Так cs50.h будзе папярэднюю апрацоўку ў файл, а затым, калі гэта кампіляцыя
гэта ў асноўным выкідваюцца пасля таго, як пераконваецца, што ўсё, што завуць правільна.
Але функцыі, вызначаныя ў CS50 бібліятэкі, якія з'яўляюцца асобнымі ад cs50.h,
тых, хто не будзе складзена асобна.
Што будзе на самой справе спусціцца ў стадыі кампаноўкі, таму мы вернемся да гэтага ў секунду.
Але, па-першае, тое, што зборка?
[Студэнт] асамблеі ў двойкавую? >> Так.
Зборка.
Мы не называем яго складання, паколькі Асамблея з'яўляецца ў значнай ступені чыстая перакладу двайковага файла.
Існуе вельмі мала логікі ў пераходзе ад Асамблеі ў двайковы фармат.
Гэта ўсё роўна, гледзячы ў табліцу, ой, у нас ёсць гэтая інструкцыя;
, Што адпавядае двайковым 01110.
І таму файлы, якія зборкі ў цэлым выхады. Аб файлах.
А. выводзяцца файлаў, што мы гаварылі раней,
як файл не трэба мець асноўную функцыю.
Любы файл можа быць складзены да. Файл вываду тых часоў, пакуль гэта правільны файл C.
Ён можа быць складзены да. °.
Цяпер, звязваючы гэта тое, што на самой справе прыносіць кучу. Аб файлах і прыводзіць іх да выкананага файла.
І тое, што кампаноўка робіць, вы можаце думаць аб CS50 бібліятэку. Файл высновы.
Гэта ўжо скампіляваных двайковых файлаў.
І так пры кампіляцыі файла, ваш hello.c, якая заклікае GetString,
hello.c кампілюецца да hello.o,
hello.o ў цяперашні час у двайковым выглядзе.
Ён выкарыстоўвае GetString, таму яна павінна перайсці да cs50.o,
і кампаноўнік smooshes іх разам і капіюе GetString ў гэты файл
і выходзіць з выкананага файла, які мае ўсе функцыі якіх яна мае патрэбу.
Так cs50.o на самай справе не аб файле, але гэта досыць блізка, што няма ніякай прынцыповай розніцы.
Такім чынам, сувязь толькі прыносіць кучу файлаў разам
што асобна ўтрымліваюць усе функцыі мне трэба выкарыстоўваць
і стварае выкананы файл, які будзе рэальна працаваць.
>> І такім чынам, гэта таксама тое, што мы гаварылі да
дзе вы можаце мець 1000. з файламі, вы сабраць іх усе. аб файлах,
які, верагодна, зойме некаторы час, то вы зменіце 1. з файлам.
Вам толькі трэба перакампіляваць, што 1. З файла, а затым перелинковки ўсё астатняе,
звязаць усе разам.
[Студэнт] Калі мы пішам сувязі lcs50?
Так, так lcs50. Гэты сцяг сігналы ў кампаноўнік, што вы павінны сувязяў у гэтай бібліятэцы.
Пытанні?
Хіба мы перайшлі двайковай іншыя, чым 5 секунд у першай лекцыі?
Не думаю.
Вы павінны ведаць усё вялікую Os, што мы перайшлі,
і вы павінны быць у стане, калі б мы далі вам функцыі,
Вы павінны быць у стане сказаць, што гэта вялікая O, груба. Або жа, Big O з'яўляецца прыблізных.
Так што калі вы бачыце, укладзеныя цыклы цыклы у параўнанні з аналагічным колькасцю рэчаў,
Int, як я, я <п; Int J, J <п - >> [студэнт] п квадрат. >> Ён мае тэндэнцыю быць паказаны ў квадраце.
Калі вы патройны ўкладзены, ён, як правіла, п кубе.
Так што такога роду рэчы вы павінны быць у стане пазначыць адразу.
Вы павінны ведаць, роду ўстаўкі і пузырьковый сартавання і сартавання зліццём, і ўсе з іх.
Гэта лягчэй зразумець, чаму яны з'яўляюцца п квадратаў і п § п і ўсё, што
таму што я думаю, што была на тэст адзін год, дзе мы ў асноўным даў вам
ажыццяўленне пузырьковый сартавання і сказаў: "Што такое час працы гэтай функцыі?"
Так што калі вы прызнаеце гэта, як пузырьковый сартавання, то вы можаце адразу сказаць, п квадрат.
Але калі вы проста паглядзіце на яе, вам нават не трэба ўсвядоміць, што гэта пузырьковый сартавання;
Вы можаце проста сказаць, што гэта рабіць гэта і гэта. Гэта п квадрат.
[Студэнт] Ці існуюць якія-небудзь жорсткія прыклады, якія вы можаце прыдумаць,
як аналагічная ідэя высветліць?
>> Я не думаю, што мы хацелі б даць Вам любыя жорсткія прыклады.
Справа ў пузырьковый сартавання прыкладна гэтак жа жорстка, як мы хадзілі,
і тое, як доўга, як вы разумееце, што вы ітэрацыі па масіве
Для кожнага элемента масіва, які будзе нешта, што п ў квадраце.
Ёсць агульныя пытанні, напрыклад, прама тут, у нас - Oh.
Літаральна на днях, Дуг заявіў: "Я вынайшаў алгарытм, які можа сартаваць масіў
"П лікаў у O (часопіс N) раз!"
Такім чынам, як мы ведаем, што гэта немагчыма?
[Неразборліва адказ студэнта] >> Так.
Па крайняй меры, вы павінны закрануць кожнага элемента ў масіве,
так што гэта немагчыма адсартаваць масіў -
Калі ўсё ў парадку несортированные, то вы будзеце тычыцца ўсё, што ў масіве,
так што гэта немагчыма зрабіць гэта менш чым за O н.
[Студэнт] Вы паказалі нам, што прыклад у стане зрабіць гэта ў O п
калі вы выкарыстоўваеце шмат памяці. >> Так.
І that's - Я забыўся, што that's - Хіба падліку роду?
Хм. Гэта цэлае алгарытм сартавання.
Я шукаў адмысловую назву для гэтага, што я не мог успомніць на мінулым тыдні.
Так. Гэтыя тыпы відаў, якія могуць выканаць рэчы ў вялікай O н.
Але ёсць абмежаванні, як вы можаце выкарыстоўваць толькі цэлыя лікі да вызначанага ліку.
Плюс, калі вы спрабуеце разабрацца нешта that's -
Калі ваш масіў 012, -12, 151, 4 млн.
тое, што адзін элемент будзе цалкам разбурыць увесь сартавання.
>> Пытанні?
[Студэнт] Калі ў вас ёсць рэкурсіўная функцыя, і ён проста робіць рэкурсіўнага выклікі
ў вяртанні заявы, што гэта хвост рэкурсіўнай,
і так бы гэта не выкарыстоўваць больш памяці падчас выканання
або, па крайняй меры, выкарыстоўваць супастаўныя памяці, як итерационные рашэння?
[Боуден] Так.
Гэта, верагодна, будзе некалькі павольней, але не зусім.
Хвост рэкурсіўных даволі добра.
Гледзячы зноў на кадры стэка, скажам, у нас ёсць асноўны
і ў нас ёсць Int бар (INT х) ці нешта яшчэ.
Гэта не ідэальны рэкурсіўнай функцыі, але вяртанне бар (х - 1).
Такім чынам, відавочна, што гэта памылкова. Вы павінны базе выпадкі і іншае.
Але ідэя тут у тым, што гэта хвост рэкурсіўнай,
што азначае, калі галоўны бар званкі ён збіраецца атрымаць свой стэк.
У гэтым кадры стэка там будзе невялікі блок памяці
, Што адпавядае яе аргументу х.
І так скажам, асноўны, здараецца, называюць Бар (100);
Такім х збіраецца пачаць, як 100.
Калі кампілятар прызнае, што гэта хвост рэкурсіўнай функцыі,
Затым, калі бара робіць яго рэкурсіўны выклік бар,
замест таго, каб новы кадр стэка, які з'яўляецца, дзе стэк пачынае расці ў асноўным,
у канчатковым выніку ён будзе працаваць у кучу і тады вы атрымаеце памылку сегментацыі
таму што памяць пачынае сутыкнення.
>> Такім чынам, замест таго, каб яго уласны кадр стэка, ён можа рэалізаваць,
Гэй, я ніколі не трэба вяртацца да гэтага кадра стэка,
так замест гэтага я проста замяніць гэты аргумент з 99, а затым пачаць бары на ўсім працягу.
І тады яна будзе рабіць гэта зноў і яна дасягне вяртання бар (х - 1),
і замест таго, каб новы кадр стэка, гэта будзе проста замяніць свой бягучы аргумент з 98
, А затым перайсці да самага пачатку бар.
Гэтыя аперацыі, замяніўшы, што 1 значэнне ў стэку і скача назад да пачатку,
даволі эфектыўным.
Так што не толькі гэтая ж выкарыстанне памяці як асобная функцыя, якая итерационного
таму што вы выкарыстоўваеце толькі 1 кадр стэка, але вы не пакутуеце мінусы
таго, каб выклікаць функцыі.
Выклік функцыі можа быць некалькі даражэй, таму што ён павінен рабіць усё гэта ўстаноўка
і дэмантажу і ўсе гэтыя рэчы.
Так што гэты хваставой рэкурсіі добра.
[Студэнт] Чаму не стварыць новыя крокі?
Таму што ён разумее, што гэта не трэба.
Выклік бар толькі што вярнуўся рэкурсіўны выклік.
Так што не трэба нічога рабіць з вяртае значэнне.
Гэта проста будзе неадкладна вярнуць яго.
Так што гэта проста збіраецца замяніць свае аргументы і пачаць усё спачатку.
А таксама, калі вы не маеце хвост рэкурсіўнай версіі,
, То вы атрымаеце ўсе гэтыя бары, дзе, калі гэты бар вяртаецца
ён павінен вярнуць яго значэнне ў гэтым, тое, што бар адразу ж вяртаецца
і вяртае яго значэнне ў гэтым, то ён проста будзе неадкладна вярнуцца
і вярнуць яго значэнне на гэтым.
Такім чынам, вы эканоміце гэтага з'яўляюцца ўсе гэтыя рэчы з стэка
З вяртаецца значэння толькі збіраецца быць перададзены ўвесь шлях назад у любым выпадку.
Так чаму б не замяніць наш спрэчка з абноўленым аргумент і пачаць усё спачатку?
Калі функцыя не з'яўляецца хваставой рэкурсіі, калі вы робіце нешта накшталт -
[Студэнт], калі бар (х + 1). >> Так.
>> Так што, калі вы змесціце яго ў стан, то вы робіце нешта з вяртае значэнне.
Ці нават калі вы проста вяртанне 2 * бар (х - 1).
Так што цяпер бар (х - 1) неабходна вярнуць для таго, каб вылічыць, што ў 2 разы значэння,
так што зараз ён сапраўды мае патрэбу ў сваім уласным асобным кадры стэка,
і зараз, як ні старайся, вы збіраецеся трэба -
Гэта не хвост рэкурсіўнай.
[Студэнт] Ці буду я спрабаваць давесці рэкурсіі імкнуцца да хваставой рэкурсіі -
[Боуден] У ідэальным свеце, але ў CS50 вам не прыйдзецца.
Для таго каб атрымаць хваставой рэкурсіі, у агульным, вы стварылі дадатковы аргумент
дзе бар адбудзецца Int х ва ў
і ў адпавядае канчатковая рэч, якую вы хочаце вярнуць.
Дык вось гэта вы будзеце вяртацца бар (х - 1), 2 * у.
Так што гэта толькі на высокім узроўні, як вы пераўтварэння рэчаў, каб быць хвастом рэкурсіўнага.
Але дадатковы аргумент -
А потым, у рэшце рэшт, калі вы дасягне сваёй базы выпадку, вы проста вярнуць у
таму што ў вас назапашваецца ўвесь час вяртаецца значэнне, што вы хочаце.
Вы, здаецца, рабілі гэта шмат разоў, але з выкарыстаннем рэкурсіўных выклікаў.
Пытанні?
[Студэнт] Можа быць, пра арыфметыку паказальнікаў, напрыклад, пры выкарыстанні радкоў. >> Вядома.
Паказальнік арыфметыка.
Пры выкарыстанні радкоў, што гэта лёгка, таму што радкі сімвалаў зоркі,
сімвалы вечныя, і заўсёды адзін байт,
і так арыфметыкі паказальнікаў эквівалентна рэгулярныя арыфметычных калі вы маеце справу з радкамі.
Давайце проста скажам, сімвал * S = "прывітанне".
Такім чынам, мы маем блок у памяці.
Яна мае патрэбу ў 6 байт, таму што вы заўсёды павінны нулём.
І знак * S будзе паказваць на пачатак гэтага масіва.
Такім чынам, з кропак.
Цяпер, гэта ў асноўным, як любы масіў працуе,
незалежна ад таго, ці было гэта вяртанне таНос ці гэта ў стэку.
Любы масіў у асноўным паказальнік на пачатак масіва,
і тады любы масіў аперацыі, любыя індэксацыі, толькі збіраецца ў гэты масіў пэўнага зрушэння.
>> Таму, калі я кажу нешта накшталт з [3], гэта будзе ёй і падлік 3 сімвала цалі
Такім чынам, з [3], мы маем 0, 1, 2, 3, такім чынам, з [3] будзе спасылацца на гэтую л.
[Студэнт] І мы маглі б дасягнуць такога ж значэння, робячы з + 3, а затым дужкі зоркі?
Так.
Гэта эквівалентна * (S + 3);
і гэта назаўсёды і заўсёды эквівалентныя незалежна ад таго, што вы робіце.
Вы ніколі не павінны выкарыстоўваць кранштэйны сінтаксісу.
Вы заўсёды можаце выкарыстоўваць * (S + 3) сінтаксіс.
Людзі, як правіла, падабаюцца кранштэйны сінтаксісу, аднак.
[Студэнт] Такім чынам, усе масівы ў рэчаіснасці з'яўляюцца проста паказальнікамі.
Існуе невялікае адрозненне, калі я кажу Int х [4] >> [студэнт] Ці значыць гэта, стварыце памяці?
[Боуден], што збіраецца стварыць 4 цэлых лікаў у стэку, таму 16 байт у цэлым.
Ён збіраецца стварыць 16 байт у стэку.
х нідзе не захоўваецца.
Гэта проста сімвал са спасылкай на старце рэч.
Таму што вы абвясцілі масіў ўнутры гэтай функцыі,
што кампілятар будзе зрабіць, гэта проста замяніць усе ўваходжання зменнай х
с, дзе гэта адбылося выбраць, каб пакласці гэтыя 16 байт.
Ён не можа зрабіць гэта з дапамогай знакаў * таму, што ёй гэта фактычна паказальнік.
Гэта бясплатна, каб потым паказаць на іншыя рэчы.
х з'яўляецца сталым. Вы не можаце мець яго кропкі да іншай масіў. >> [Студэнт] Добра.
Але гэтая ідэя, гэтая індэксацыя, такое ж, незалежна ад таго, ці з'яўляецца гэта традыцыйным масівам
або, калі гэта паказальнік на нешта або, калі гэта паказальнік на malloced масіва.
І на самай справе, гэта так эквівалентнай, што гэта таксама адно і тое ж.
Гэта на самай справе проста азначае, што ўнутры дужак і тое, што засталося за дужкі,
складае іх, і разыменовывает.
Так што гэта толькі ж сілу, як * (S + 3) ці з [3].
[Студэнт] Можа ў вас ёсць паказальнікі, якія паказваюць на 2-мерных масіваў?
>> Гэта цяжэй. Традыцыйна, няма.
2-мерны масіў знаходзіцца ўсяго ў 1-мерны масіў з некаторым зручны сінтаксіс
таму што, калі я кажу Int х [3] [3], гэта сапраўды толькі 1 масіў з 9 значэнняў.
І таму, калі я індэксам, кампілятар ведае, што я маю на ўвазе.
Калі я скажу, х [1] [2], ён ведае, я хачу пайсці на другім радку, так што ён збіраецца прапусціць першыя 3,
, А затым яна хоча Другое у тым, што так яно збіраецца атрымаць гэта.
Але гэта яшчэ толькі аднамерны масіў.
І таму, калі я хацеў прысвоіць паказальнік на гэты масіў,
Я б сказаў Int * р = х;
Тып х проста -
Гэта груба кажучы тыпу х, так як гэта ўсяго толькі сімвал, і гэта не фактычнай зменнай,
Але гэта ўсяго толькі Int *.
х гэта проста паказальнік на пачатак гэтага. >> [Студэнт] Добра.
І таму я не буду мець магчымасць доступу [1] [2].
Я думаю, што ёсць адмысловы сінтаксіс для аб'явы паказальніка,
нешта смешнае, як Int (* р [-. нешта абсалютна смешна, я нават не ведаю.
Але ёсць сінтаксіс для аб'явы паказальнікаў, як з дужкамі і рэчы.
Ён не можа нават дазволіць вам зрабіць гэта.
Я магу азірнуцца на тое, што б сказаць мне праўду.
Я буду шукаць яго пазней, калі ёсць сінтаксіс кропкі. Але вы ніколі не ўбачыце.
І нават сінтаксіс вельмі архаічная, што калі вы выкарыстоўваеце яго, людзі будуць збітыя з панталыку.
Шматмерныя масівы з'яўляюцца даволі рэдкімі, як гэта.
Вы ў значнай ступені -
Ну, а калі вы робіце матрыцу рэчаў ён не збіраецца быць рэдкімі,
але ў C вы рэдка будзеце выкарыстоўваць шматмерныя масівы.
Так. >> [Студэнт] Скажам, у вас ёсць вельмі доўгі масіў.
>> Такім чынам, у віртуальнай памяці, яна, здавалася б, усё запар,
як элементы побач адзін з адным,
але і ў фізічнай памяці, гэта было б магчыма, што быць падзеленыя? >> Так.
Як віртуальная памяць працуе гэта толькі аддзяляе -
Блок размеркавання ўяўляе сабой старонку, якая мае тэндэнцыю быць 4 кілабайта,
і таму, калі працэс кажа, эй, я хачу выкарыстоўваць гэтую памяць,
Аперацыйная сістэма збіраецца вылучыць яе 4 кілабайта, што мала блок памяці.
Нават калі вы выкарыстоўваеце толькі адзін маленькі байт ў цэлы блок памяці,
Аперацыйная сістэма збіраюся даць яму поўны 4 кілабайта.
Так што гэта азначае, я мог бы - скажам, гэта мой стэк.
Гэты стэк могуць быць падзеленыя. Мой стэк можа быць мегабайты і мегабайты.
Мой стэк можа быць велізарным.
Але сам стэк павінен быць разбіты на асобныя старонкі,
, Які, калі мы паглядзім на тут скажам, гэта наша памяць,
калі ў мяне ёсць 2 гігабайта аператыўнай памяці, гэта сапраўды адрасе 0 як нулявы байт маёй памяці,
і гэта складае 2 гігабайта на ўсім шляху сюды.
Так гэтай старонцы можа адпавядаць гэтаму блоку тут.
Гэтая старонка можа адпавядаць гэтаму блоку тут.
Гэта адна можа адпавядаць гэтым сюды.
Такім чынам, аперацыйная сістэма вольная прызначыць фізічнай памяці
у асобных старонак адвольна.
А гэта значыць, што калі гэта адбудзецца, мяжа асядлаць масіва,
Масіў здараецца, пакінуў гэта і права гэты парадак старонак,
Затым гэты масіў будзе падзелены ў фізічнай памяці.
А потым, калі вы выходзіце з праграмы, калі працэс скончыцца,
гэтыя адлюстравання атрымаць сцёртыя, а затым яна свабодна выкарыстоўваць гэтыя маленькія блокі для іншых рэчаў.
Яшчэ пытанні?
[Студэнт] арыфметыкі паказальнікаў. >> Ах так.
Струны былі лягчэй, але, гледзячы на ​​тое, як цэлымі,
Такім чынам, вернемся да Int х [4];
Ці з'яўляецца гэта масіў ці гэта паказальнік на malloced масіў з 4 лікаў,
гэта будзе разглядацца такім жа чынам.
[Студэнт] Так масіваў у кучы?
[Боуден] Масівы не ў кучы. >> [Студэнт] Ох.
>> [Боуден] Гэты тып масіва, як правіла, у стэку
калі Вы заявіў на - ігнараванне глабальных зменных. Не выкарыстоўвайце глабальныя зменныя.
Усярэдзіне функцыі Я кажу Int х [4];
Ён збіраецца стварыць 4-цэлы лік блокаў у стэку для гэтага масіва.
Але гэта таНос (4 * SizeOf (INT)); будзе ісці ў кучу.
Але пасля гэтага моманту я магу выкарыстоўваць х і р у значнай ступені тымі ж спосабамі,
акрамя выключэнняў, я ўжо гаварыў пра вас можна перапрызначыць р.
Тэхнічна, іх памеры некалькі адрозніваюцца, але гэта зусім не мае значэння.
Вы ніколі не выкарыстоўваць іх памераў.
Р я магу сказаць, р [3] = 2, або х [3] = 2;
Вы можаце выкарыстоўваць іх сапраўды гэтак жа спосабамі.
Так што арыфметыка паказальнікаў цяпер - так.
[Студэнт] Вы не павінны рабіць р * калі ў вас ёсць дужкі?
Дужках няяўных спасылак. >> Добра.
На самай справе, і тое, што вы кажаце з вы можаце атрымаць шматмерныя масівы
з паказальнікамі, што вы можаце зрабіць нешта накшталт, скажам, Int ** рр = таНос (SizeOf (INT *) * 5);
Я проста напісаць усё гэта ў першую чаргу.
Я не хацеў гэтага.
Добра.
Што я зрабіў тут - Гэта павінна быць рр [I].
Так п.п. гэта паказальнік на паказальнік.
Вы mallocing п.п. паказвае на масіў з 5 зорак Int.
Такім чынам, у памяці ў вас у стэку С.
Гэта будзе паказваць на масіў з 5 блокаў, якія ўсё самі паказальнікі.
А потым, калі я таНос сюды, я таНос, што кожны з гэтых асобных паказальнікаў
павінен паказваць на асобны блок з 4 байт ў кучы.
Такім чынам, гэта паказвае на 4 байта.
А гэта паказвае на іншыя 4 байт.
>> І ўсе яны паказваюць на сваіх 4 байт.
Гэта дае мне спосаб зрабіць шматмерным рэчы.
Я мог бы сказаць п.п. [3] [4], але цяпер гэта не тое ж самае, шматмерныя масівы
таму што шматмерныя масівы ў яе перакладзе [3] [4] у адну зрушэнне ў масіве х.
Гэта разыменовывает р, доступ да трэцяга індэкса, то, што разыменовывает
і доступы - 4 будуць лічыцца несапраўднымі - другі індэкс.
У той час, калі мы былі Int х [3] [4] да як мнагамерны масіў
і пры падвойным кранштэйне гэта сапраўды толькі адзін разнаймення,
Вы пасля аднаго паказальніка, а затым зрушэнне,
гэта сапраўды 2D спасылкі.
Вы вынікаеце 2 асобныя паказальнікі.
Такім чынам, гэта таксама тэхнічна дазваляе мець шматмерныя масівы
дзе кожны масіва розных памераў.
Таму я думаю, зубчастыя шматмерных масіваў з'яўляецца тое, што яна называецца
так як на самой справе першае, што можа паказваць на тое, што мае 10 элементаў,
Другое, што можа паказваць на тое, што мае 100 элементаў.
[Студэнт] Ці ёсць абмежаванне на колькасць паказальнікаў вы можаце мець
якія паказваюць на іншыя паказальнікі? >> Не.
Вы можаце мець Int ***** р.
Вярнуцца да арыфметыцы з паказальнікамі - >> [студэнт] Ох. >> Так.
[Студэнт] Калі ў мяне ёсць Int *** р а затым я разнаймення, і я кажу р * роўная гэтаму значэнні,
гэта толькі збіраецца зрабіць 1 ўзровень разнаймення? >> Так.
Так што, калі я хачу атрымаць доступ тое, што апошні паказальнік накіраваны на -
Тады вы *** р. >> Добра.
Так што гэта р паказвае на 1 блок, які паказвае на іншы блок, які паказвае на іншы блок.
Тады, калі вы робіце * р = нешта іншае, то вы змяняеце гэтую
Зараз, каб паказаць на другі блок. >> Добра.
>> [Боуден] І калі яны былі malloced, то вы цяпер ўцечка памяці
калі вам пашчасціла мець розныя спасылкі з гэтых
Паколькі вы не можаце вярнуцца ў тыя, што вы проста выкінулі.
Паказальнік арыфметыка.
Int х [4]; збіраецца вылучыць масіў з 4 лікаў
дзе х будзе паказваць на пачатак масіва.
Таму, калі я кажу нешта накшталт X [1], я хачу, каб гэта азначала ісці на другі цэлы лік у масіве,
, Які быў бы гэтаму.
Але на самай справе, гэта 4 байта ў масіве, так як гэта цэлы лік займае 4 байта.
Такім чынам, зрушэнне 1 на самай справе азначае зрушэнне 1
раз памер незалежна ад тыпу масіва.
Гэта масіў цэлых лікаў, таму ён ведае, што трэба рабіць 1 раз памер Int, калі ён хоча, каб кампенсаваць.
Іншы сінтаксіс. Памятаеце, што гэта эквівалентна * (х + 1);
Калі я кажу паказальнік + 1, тое, што вяртае гэта адрас, што паказальнік захоўвання
плюс 1 раз памер тып паказальніка.
Такім чынам, калі х = ox100, то х + 1 = ox104.
І вы можаце злоўжываць гэтым і сказаць нешта накшталт сімвал * C = (сімвал *) х;
і зараз з будзе той жа адрас, х.
З будзе роўная ox100,
але з + 1 будзе роўная ox101
З арыфметыкай паказальніка залежыць ад тыпу паказальнік, які вы дадаеце ст.
Такім чынам, з + 1, ён глядзіць на C, гэта знакавы паказальнік, так што ён збіраецца дадаць 1 разы памер сімвалаў,
які заўсёды будзе на 1, так што вы атрымаеце 101,
а калі я зраблю х, якая таксама яшчэ 100, х + 1 будзе 104.
[Студэнт] Ці можна выкарыстоўваць C + +, у мэтах прасоўвання паказальніка на 1?
Так, можна.
Вы не можаце зрабіць гэтага, таму што з х х гэта проста сімвал, гэта пастаянная, вы не можаце змяніць х.
>> Але з адбываецца, каб быць проста паказальнік, так што C + + з'яўляецца цалкам дапушчальным, і яна будзе павялічвацца на 1.
Калі з проста Int *, то C + + будзе 104.
+ + Робіць арыфметыку паказальнікаў гэтак жа, як з + 1 зрабіў бы арыфметыкі паказальнікаў.
На самай справе, як шмат такіх рэчаў, як сартавання зліццём -
Замест таго каб ствараць копіі рэчаў, вы можаце замест гэтага прайсці -
Як калі б я хацеў перадаць гэтую палову масіва - давайце сцерці частка гэтага.
Скажам, я хацеў бы перадаць гэтую бок масіва ў функцыю.
Што б я перадаць гэтую функцыю?
Калі я праходжу х, я перадаю гэты адрас.
Але я хачу, каб прайсці гэты канкрэтны адрас. Так што я павінен прайсці?
[Студэнт] паказальнік + 2?
[Боуден] Такім чынам, х + 2. Так.
Гэта будзе гэты адрас.
Вы таксама вельмі часта бачу гэта як х [2], а затым адрас гэтага.
Такім чынам, вы павінны ўзяць на адрас, таму што кранштэйны няяўных спасылак.
х [2] спасылаецца на значэнне, якое знаходзіцца ў гэтым полі, а затым вы хочаце адрас гэтага акна,
так што вы кажаце і х [2].
Дык вось, як нешта сартавання зліццём, дзе вы хочаце перадаць палову спісу, каб нешта
Вы сапраўды проста перадаць і х [2], і ў цяперашні час, наколькі рэкурсіўны выклік, то,
мой новы масіў пачынаецца там.
Апошнія пытанні хвіліну.
[Студэнт] Калі мы не будзем ставіць амперсанда або - што, што называецца? >> Star?
[Студэнт] Star. >> Тэхнічна, аператар разнаймення, але - >> [студэнт] Dereference.
>> Калі мы не ставім зоркі або амперсанда, што адбудзецца, калі я проста скажу, у = х і х з'яўляецца паказальнікам?
Які тып у? >> [Студэнт] Я проста кажу, што гэта паказальнік 2.
Так што калі вы толькі што сказалі у = х, зараз х і ў паказваюць на адно і тое ж. >> [Студэнт] паказваюць на тое ж самае.
І калі х Int паказальніка? >> Было б скардзіцца, таму што вы не можаце прызначыць паказальнікаў.
[Студэнт] Добра.
Памятаеце, што паказальнікі, хоць мы і прыцягнуць іх, як стрэлы,
на самай справе ўсё, што яны крамы - Int * х - сапраўды ўсё х захоўвання нешта накшталт ox100,
якія мы, здараецца, якія прадстаўляюць як указанне на блоку захоўваецца 100.
Таму калі я кажу Int * у = х, я проста капіяванне ox100 у у,
якія мы толькі збіраемся прадставіць як у, таксама паказваючы на ​​ox100.
І калі я кажу Int я = (INT) х, тады я маю намер захоўваць любыя значэння ox100 з'яўляецца
ўнутры яго, але цяпер гэта будзе інтэрпрэтавацца як цэлае, а не паказальнік.
Але для гэтага трэба літых ці ж ён будзе скардзіцца.
[Студэнт] Такім чынам, вы маеце на ўвазе, каб кінуць -
Гэта збіраецца быць ліцця Int х ці ліццё Int у?
[Боуден] Што?
[Студэнт] Добра. Пасля гэтых дужках там будзе х ці ау там?
>> [Боуден] Альбо. х і ў з'яўляюцца эквівалентнымі. >> [Студэнт] Добра.
Таму што яны абодва паказальніка. >> Так.
[Студэнт] Таму было б захоўваць шаснаццатковае цэлы лік 100 у форме? >> [Боуден] Так.
Але не значэнне таго, што гэта паказвае.
[Боуден] Так. >> [Студэнт] Такім чынам, толькі адрас у цэлалікавых выглядзе. Добра.
[Боуден] Калі вы хацелі б па некаторай дзіўнай прычыне,
Вы маглі б мець справу выключна з паказальнікамі і ніколі не мець справу з цэлымі лікамі
і проста быць як Int * х = 0.
Тады вы збіраецеся атрымаць сапраўды блытаюць раз арыфметыкі паказальнікаў пачынае адбывацца.
Так што лічбы, якія яны захоўваюць не маюць сэнсу.
Гэта проста, як вы ў канчатковым выніку іх інтэрпрэтацыі.
Так што я свабодна капіяваць ox100 ад Int * у цэлы лік,
і я свабодна прызначаць - ты, верагодна, збіраюся крычаць на што не ліццё -
Я вольны прызначыць нешта накшталт (Int *) ox1234 ў гэтай адвольнай * Int.
Так ox123 гэтак жа верны адрас памяці, як гэта і ў.
І ў здараецца, вярнуць тое, што з'яўляецца ў значнай ступені ox123.
[Студэнт] Гэта было б сапраўды выдатна шлях ад шаснаццатковай ў дзесятковую форму,
падабаецца, калі ў вас ёсць паказальнік, і вы кінулі яго ў выглядзе цэлага ліку?
[Боуден] Вы сапраўды можаце проста друкаваць, выкарыстоўваючы як Printf.
Скажам, у мяне ёсць Int у = 100.
Такім чынам, Е (% г \ п - як вы ўжо ведаеце - друк, што як цэлае, х%.
Мы проста раздрукаваць яго як шаснаццатковае.
Такім чынам, паказальнік не захоўваецца ў шаснаццатковым,
і цэлае не захоўваецца ў выглядзе дзесятковай.
Усе захоўваецца ў двайковым выглядзе.
Гэта толькі, што мы, як правіла, каб паказаць, паказальнікі, як шаснаццатковае
таму што мы думаем пра рэчы, у гэтых 4-байтовых блокаў,
і адрасы памяці, як правіла, знаёмыя.
Мы як, калі ён пачынаецца з BF, то яно адбудзецца, будзе ў стэку.
Так што гэта проста наша інтэрпрэтацыя паказальнікі, як шаснаццатковае.
Добра. Любы апошніх пытанняў?
>> Я буду тут трохі пасля, калі ў вас ёсць што-то яшчэ.
І гэта канец.
>> [Студэнт] Ура! [Апладысменты]
>> [CS50.TV]