[Powered by Google Translate] [Раздел 4 - по-удобни]
[Роб Боудън - Харвардския университет]
[Това е CS50. - CS50.TV]
Ние имаме тест утре, в случай, вие не знаете, че.
Това е в основата на всичко, което би могъл да види в клас или да са видели в клас.
Това включва указатели, въпреки че те са много стара тема.
Би трябвало поне да разбираш от високите нива на тях.
Всичко, което беше преминал в клас трябва да се разбере за теста.
Така че, ако имате въпроси по тях, можете да ги помолите.
Но това ще бъде много на студентите сесия, когато вие задавате въпроси,
така че се надяваме хората имат въпроси.
Някой има ли въпроси?
Да. >> [Ученик] Може ли да отида указатели отново?
Аз ще отида указатели.
Всички променливите задължително да живеят в паметта,
но обикновено не се тревожи за това и просто казват, X + 2 и г + 3
и компилаторът ще разбера, когато нещата се живее за вас.
След като имаш работа с указатели, сега вече изрично използването на тези адреси от паметта.
Така че една променлива само ще живеят на един адрес във всеки даден момент.
Ако искаме да обяви показалеца, какво е вид ще изглежда?
>> Искам да обяви стр. показалеца. Какво означава вид изглежда?
[Ученик] Int * р. >> Да. Така Int * р.
И как мога да го насочите към х? >> Студент Ampersand.
[Bowden Така амперсанд е буквално нарича адрес на оператора.
Така че, когато казвам & X, адресът в паметта на променливата х.
Така че сега имам показалеца стр., и където и да е в моя код мога да използвам * р
или мога да използвам х и тя ще бъде точно същото нещо.
(* P). Какво е това? Какво прави тази звезда?
[Ученик] Това означава стойност в този момент. >> Да.
Така че, ако ние гледаме на него, той може да бъде много полезно да се ползват от диаграми
когато това е малка кутийка с памет за Х, който се случва да има стойност 4,
тогава имаме малка кутийка с памет за стр.,
и така стр. точки на х, така че ние начертайте стрелка от стр. на х.
Така че, когато казваме * р Казваш, отидете на полето, което е стр..
Star е да следвате стрелката и след това правя каквото си искам с тази кутия точно там.
Затова мога да кажа * р = 7, и че ще отиде в полето, което е х, а промяна, която до 7.
Или мога да кажа, вътр Z = * р * 2 Това е объркващо, защото е звезда, звезда.
Една звезда е dereferencing стр., друга звезда се умножи по две.
Забележете, може да има също толкова добре замени * р х.
Можете да ги използвате по същия начин.
И тогава по-късно аз може да има стр. точка за нещо напълно ново.
Мога само да кажа, р = &z;
Така че сега п вече не сочи към х посочва Z.
И всеки път, когато правя * р е същото, както прави Z.
Така полезно нещо за това е, веднъж да започнем класирането им функции.
>> Това е нещо безполезно да обяви показалеца, който сочи към нещо
и след това просто го dereferencing
, когато би могъл да използва оригиналната стойност, за да се започне.
Но когато влязат в функции - така че нека да кажем, че имаме някои функции, вътр Foo
който взема показалеца и просто прави * р = 6;
Както видяхме преди с суап, не можеш да направиш ефективен суап и отделна функция
просто минават цели числа, защото всичко в C е винаги минава по стойност.
Дори когато сте преминаване указатели, който минава по стойност.
Просто така се случи, че тези стойности са адреси от паметта.
Така че, когато казвам, Foo (п); съм преминаване на показалеца във функцията на Foo
и след това Foo * р = 6;
Така че в рамките на тази функция, все още е равностойно на х * р,
но не мога да х вътрешността на тази функция, защото това не е обхват в рамките на тази функция.
Така * р = 6 е единственият начин да получите достъп до локалната променлива от друга функция.
Или, показалки са единственият начин да получите достъп до локалната променлива от друга функция.
[Ученик] Да речем, че иска да се върне указател. Как точно се прави това?
[Bowden връща указател, както в нещо като Int Y = 3; връщане & Y? >> Студент Да.
[Bowden Добре. Никога не трябва да направите това. Това е лошо.
Мисля, че видях в тези лекционните слайдове започна да се вижда цялата тази схема на паметта
тук имаш памет адрес 0
и тук имате адреса в паметта четири участия или 2 до 32.
Тогава имаш някои неща и някои неща и тогава ще трябва стака си
и имаш куп, който току-що започва да учи, расте.
[Ученик] не е на куп над комина?
>> Да. Грамада е на върха, нали? >> Студент, той сложи 0 на върха.
[Ученик] О, той сложи 0 на върха. >> [Ученик] О, добре.
Отговорности: Навсякъде с CS50 ти започваш да го видя този начин. >> Студент Добре.
Това е просто, че когато сте първата виждам стакове,
харесва, когато мислите за комин мислите за подреждане на нещата на върха на един друг.
Така че ние сме склонни да се обърнете наоколо, така че стека се разраства като комин обикновено
вместо стека висящи. >> Студент не купища технически растат, все пак?
Това зависи от какво имаш предвид под растат.
Стак и куп винаги растат в противоположни посоки.
Комин винаги е в смисъл, че тя расте
към по-високи адреси на паметта, както и на куп се разраства
в това, че той се разраства към по-ниски адреси на паметта.
Така че на върха е 0, а дъното е висока адреси на паметта.
И двамата нараства, само в противоположни посоки.
[Ученик] Аз просто означава, че защото ти каза, че стак на дъното
защото тя изглежда по-интуитивно, защото стека, за да започне на върха на купчина,
купчина е на върха на себе си, така че това е - >> Да.
Можете също така, че на куп расте и по-големи, но стека така.
Така че стека е едно, че ние някак си искаме да покажем расте.
Но навсякъде, където погледнете по друг начин ще се покаже адрес 0 на върха
и най-високата адреса в паметта на дъното, така че това е обичайната гледка на паметта.
>> Имате ли въпрос?
[Ученик] Може ли да ни кажете повече за куп?
Да. Ще стигнем и до това в секунда.
Първо, защо завръщането и у е лошо нещо,
на стека имате куп на стека рамки, които представляват всички функции
, които са били призовани.
Така че, без да обръща внимание на предишните неща, в началото на стака ви е винаги ще бъде основната функция
тъй като това е първата функция, която се нарича.
И тогава, когато ти се обадя друга функция, стека се ще расте.
Така че, ако аз наричам някои функции, Foo, и тя си има своя собствена рамка стека,
може да се обадите на някои функции, бар, тя си има своя собствена рамка стека.
И лента, може да бъде рекурсивна и тя може да се обадите,
и така, че втората покана в бара ще се получи своя собствена рамка стека.
И така, какво се случва в тези стека рамки са всички локални променливи
и на функционалните аргументи, които
Всички неща, които са локално обхват на тази функция в тези стека рамки.
Така че това означава, че когато казах, нещо като бар е функция,
Аз съм просто ще обяви цяло число, а след това се върнете показалец към това число.
Така, откъде идва у живееш?
[Студент г. живее в бара. >> Bowden Да.
Някъде в този малък площад памет-малка е квадрат, който има г. в него.
Когато се върна & Y, Връщам указател към този малък блок от памет.
Но тогава, когато функцията връща, си стак рамка стане показа стека.
И това е защо тя се нарича стека.
Това е като структура на стека данни, ако знаете какво е това.
Или дори като купчина тави винаги е например,
Основната ще отиде на дъното, а след това първата функция, която ти се обадя ще си отиде в началото на това,
и не можете да се върнете към основното, докато се върнете от всички функции, които са били наречени
, които са поставени в началото на това.
>> [Ученик] Така че, ако е направил върне г., тази стойност е обект на промяна без предупреждение.
Да, it's - >> [ученик] биха могли да бъдат презаписани. >> Да.
Това е напълно - Ако се опитате и -
Това би било едно цяло число бар *, защото това е връщане на показалеца,
така че неговото завръщане е от тип INT *.
Ако се опитате да използвате връщаната стойност от тази функция, това е неопределено поведение
, защото това показалецът се посочва лоша памет. >> Студент Добре.
И какво, ако, например, обяви Int * Y = изчистване (sizeof (INT))?
Така е по-добре. Да.
[Ученик] Ние говорихме за това как, когато плъзнете неща в нашия кошчето
всъщност те не са изтрити, ние просто губят указатели.
Така че в този случай ние всъщност изтриете стойността или е все още там в памет?
За по-голямата си част, тя все още ще бъде там.
Но нека да кажем, че сме се случи, да се обадя на някои друга функция, Баз.
Баз ще получи своя собствена рамка стека тук.
Ще бъде презаписване на всички тези неща,
и тогава, ако по-късно се опита да използвате показалеца, че имаш преди,
това няма да бъде една и съща стойност.
Това ще да са се променили, само защото сте се обадили на функция Баз.
[Ученик] Но не ние, бихме все още се три?
[Bowden] По всяка вероятност, ще го направиш.
Но не можем да разчитаме на това. С просто казва неопределено поведение.
>> [Ученик] О, го прави. Добре.
Така че, когато искате да се върнете указател, това е мястото, където изчистване влезе в употреба.
Пиша всъщност се върне изчистване (3 * sizeof (INT)).
Ще отидем изчистване повече в секунда, но идеята за изчистване на вашите локални променливи
винаги вървят в стека.
Всичко, което е malloced отива на куп, и то завинаги и винаги ще бъде на куп
докато изрично го освободи.
Така че това означава, че когато изчистване нещо, то се случва да оцелее след функцията връща.
[Ученик] Ще оцелее след програмата спира да работи? >> Бр.
Добре, така че ще бъде там, докато програмата е начина, по който работи. >> Да.
Ние можем да отидем подробности за това, което се случва, когато програмата спира да работи.
Може да се наложи да ми напомня, но това е съвсем отделно нещо.
[Ученик] Така изчистване създава показалеца? >> Да.
Изчистване - >> [ученик] Мисля, изчистване обозначава блок от памет, че показалецът да използвате.
[Bowden] Искам тази диаграма отново. >> [Ученик] Така че тази функция работи, нали?
[Ученик] Да, изчистване определи блок от памет, които можете да използвате,
и след това го връща адреса на първия блок от този спомен.
>> [Bowden Да. Така че, когато изчистване, вие вземете някои блок на паметта
, че в момента на куп.
Ако грамада е твърде малък, а след това на куп е просто ще растат, а тя расте в тази посока.
Така че нека да кажем грамада е твърде малък.
Тогава това е за да растат малко и връща указател към този блок, който току-що нарасна.
Когато безплатни неща, правиш повече място в купчина
така че след това по-късно се обадя да изчистване да го използвате отново памет, която преди това е освободен.
Най-важното нещо за изчистване и безплатен е, че той ви дава пълен контрол
за целия живот от тези запаметяващи блокове.
Глобалните променливи са винаги жив.
Локални променливи са живи в тяхното приложно поле.
Веднага след като миналото презрамки къдрава, локални променливи са мъртви.
Malloced паметта е жива, когато искате да си жив
и след това се освобождава, когато го кажа, да бъдат освободени.
Това всъщност са единствените три вида памет, наистина.
Има автоматично управление на паметта, която е стека.
Нещата се случват автоматично.
Когато казват, че INT х памет се разпределя за INT х.
Когато х излиза на обхвата, паметта е върната х.
Тогава там е динамично управление на паметта, което е това, което изчистване,
което е, когато имате контрол.
Динамично реши памет, когато трябва и не трябва да се разпределят.
И тогава там е статичен, което просто означава, че тя живее вечно,
което е, какви са глобалните променливи.
Те са винаги в паметта.
>> Въпроси?
[Ученик] Можете ли да определите блок само с помощта на фигурни скоби
но няма да има, ако декларация или изявление, докато или нещо подобно?
Можете да дефинирате блок, като във функция, но има фигурни скоби.
[Ученик] Значи не може просто да са като случаен чифт фигурни скоби в кода си
, които имат локални променливи? >> Да, можете.
Вътре INT бар бихме могли да имаме {Int Y = 3;}.
Това е трябвало да бъде тук.
Но това напълно определя обхвата на вътр г..
След тази втора презрамки къдрава, Y не може да се използва повече.
Вие почти никога не направите това, все пак.
Да се ​​върнем към това, което се случва, когато програмата приключи,
има вид на недоразумение / половин лъжа, че ние даваме само за да направи нещата по-лесни.
Ние ви кажа, че когато се задели памет
разпределяне на част парче RAM за тази променлива.
Но вие не сте наистина директно докосване RAM някога в своите програми.
Ако мислите, че от това, как Нарисувах
И действително, ако мине в GDB ще видите едно и също нещо.
Независимо от това колко пъти изпълнявате вашата програма или каква програма да работите,
стека винаги ще започнете -
вие винаги ще видите променливи около нещо адрес oxbffff.
Това е обикновено някъде в този регион.
Но как може две програми вероятно са указатели към същата памет?
[Ученик] Има някои произволно наименование на мястото, където е трябвало да бъде oxbfff на RAM
, които действително могат да бъдат на различни места, в зависимост от това, когато е била извикана.
Да. Терминът е виртуална памет.
Идеята е, че всеки един процес, всяка една програма, която се изпълнява на вашия компютър
има своя собствена - нека приемем, че 32 бита - напълно независима адресно пространство.
Това е адресно пространство.
Той има свои собствени напълно независими 4 гигабайта да се използват.
>> Така че, ако ви свършат две програми едновременно, тази програма се вижда 4 гигабайта за себе си,
тази програма се вижда 4 гигабайта за себе си,
и е невъзможно за тази програма за сочен указател
и в крайна сметка с памет от тази програма.
И това, което е виртуална памет е картографиране от адресното пространство на процесите,
към действителните неща на RAM.
Така че това е за вашата операционна система, за да знаете, че
хей, когато този човек dereferences показалеца oxbfff, че всъщност означава
че той иска RAM байт 1000,
като има предвид, че ако тази програма dereferences oxbfff, той наистина иска RAM байт 10000.
Те могат да бъдат произволно далеч един от друг.
Това е вярно дори на нещата в рамките на един-единствен адрес процеси пространство.
Така че, като гледа всичките 4 гигабайта за себе си, но нека да кажем -
[Студент ли всеки един процес -
Да кажем, че имате компютър само с 4 гигабайта RAM.
Всеки един процес цели 4 гигабайта? >> Да.
4 гигабайта го вижда обаче е лъжа.
Това е просто смята, че разполага с цялата тази памет, защото тя не знае съществува какъвто и да е друг начин.
Той ще използва само толкова памет, тъй като наистина има нужда.
Операционната система няма да даде RAM за този процес
ако това не е използване на паметта, в целия този регион.
Това няма да го дам памет за този регион.
Но идеята е, че - Опитвам се да мисля за - Не мога да мисля за аналогия.
Аналогии са трудни.
Един от проблемите на виртуалната памет или едно от нещата, това е решаване на
е, че процесите трябва да бъде напълно наясно с един от друг.
И така, можете да напишете всяка програма, която само dereferences каквато и да е показалецът,
като просто напишете програма, която казва * (ox1234),
и това е dereferencing памет адрес 1234.
>> Но това е до операционната система, за да превежда какво 1,234 средства.
Така че, ако 1234 се случва да бъде валиден адрес на памет за този процес,
като че ли е на стека или нещо, то това ще върне стойността на тази памет адрес
доколкото процесът знае.
Но ако 1234 не е валиден адрес, както се случва да се приземи
в някаква малка част от паметта, което е извън стека и извън куп
и не сте наистина, че това е, когато нещата като segfaults
защото сте докосва памет, която не трябва да се докосва.
Това също е вярно -
32-битова система, 32 бита означава, че имате 32 бита за определяне на адрес от паметта.
Това е защо указатели са 8 байта, защото 32 бита са 8 байта - или 4 байта.
Указатели са 4 байта.
Затова, когато видите указател като oxbfffff, че е
В рамките на всяка програма може просто да се изгради произволна показалеца,
от ox0 8 f's вол - ffffffff.
[Ученик] не казват, че са 4 байта? >> Да.
[Ученик] Тогава всеки байт ще има - >> Bowden шестнадесетичен вид.
Шестнадесетичен - 5, 6, 7, 8. Така указатели вие винаги ще видите в шестнадесетичен.
Това е просто как ние класифицираме указатели.
На всеки две цифри на шестнадесетичен е 1 байт.
Така че ще бъде 8 шестнадесетични цифри за 4 байта.
Така че всеки един показалеца върху 32-битова система ще бъде 4 байта,
което означава, че във вашия процес може да създава каквито и произволни 4 байта
и да направи показалеца от него,
което означава, че, доколкото той е наясно, че може да се обърне целия 2 до 32 байта памет.
Въпреки че тя не наистина имат достъп до тази,
дори ако компютърът ви има само 512 мегабайта, тя смята, че е, че много памет.
И операционната система е достатъчно умен, че това ще е само да разпредели това, което действително се нуждаят.
Тя не просто отидете, о, нов процес: 4 участия.
>> Да. >> [Ученик] Какво вола? Защо го пиша?
Това е просто символ за шестнадесетично.
Когато видите започват с номер вол, последователните нещата са в шестнадесетичен вид.
[Ученик] обяснява какво се случва, когато програмата приключи. >> Да.
Какво се случва, когато програмата приключи, е операционната система
само изтрива съпоставяния, че за тези адреси, и това е всичко.
Операционната система може просто да даде този спомен в друга програма да се използва.
[Ученик] Добре.
Така че, когато разпределят нещо на куп или стек или глобални променливи или нещо,
всички те просто изчезват веднага след като програмата приключва
защото операционната система вече е свободен да дам, че паметта какъвто и да е друг начин.
[Ученик] Въпреки че вероятно все още има ценности, написани на? >> Да.
Стойностите вероятно са все още там.
Това е просто, че ще бъде трудно да се добере до тях.
Това е много по-трудно да се добере до тях, отколкото е да се получи на изтрити файлове
защото изтрити файлове вид седи там за дълго време, а твърдият диск е доста по-голям.
Така че ще да презапишете различни части на паметта
преди да се случи, за да презапишете парче от паметта, че този файл да бъде използван в.
Но основната памет, RAM, преминете през много по-бързо,
така че става много бързо да бъдат презаписани.
Въпроси за това или нещо друго?
[Ученик] Имам въпроси относно различна тема. >> Добре.
Някой има ли въпроси по тази тема?
>> Добре. Различна тема. >> Студент Добре.
Щях чрез някои от практика тестове,
и в един от тях говори за sizeof
и стойността, която се връща или различни променливи видове. >> Да.
И той каза, че INT така и в дългосрочен както връщането 4, така че те са двете с дължина 4 байта.
Има ли някаква разлика между вътр и дълъг, или то е едно и също нещо?
Да, има разлика.
C стандарт -
Аз съм най-вероятно ще да се забъркваш.
C стандарт е точно като C е официалната документация на C.
Това е това, което казва.
Така че C стандарт просто казва, че Чар завинаги и винаги ще бъде един байт.
Всичко след това - кратко винаги е точно определено като по-малка или равна на знака.
Това може да бъде строго по-голяма, отколкото, но не е положително.
Число е просто определено е по-голяма или равна на кратко.
И дълъг е просто определя като по-малка или равна на вътр.
И дълго е по-голяма или равна дълго.
Така че единственото нещо, C стандарт определя относителната поръчването на всичко.
Действителният размер на паметта, че нещата заемат обикновено е до изпълнението,
но това е доста добре дефинирани в този момент. >> Студент Добре.
Така шорти са почти винаги ще е 2 байта.
Интеджър са почти винаги ще бъде на 4 байта.
Дълги чак са почти винаги ще е 8 байта.
И копнее, това зависи от това дали сте с помощта на 32-битова или 64-битова система.
Така че дълго ще да отговаря на типа на системата.
Ако използвате 32-битова система като техника, ще бъде 4 байта.
Ако използвате 64-битов като много от последните компютри, тя ще бъде 8 байта.
>> Интеджър са почти винаги 4 байта в този момент.
Дълги дългите почти винаги са 8 байта.
В миналото, интеджър да бъде само два байта.
Но забележете, че това напълно отговаря на тези отношения и по-голяма от равна на.
Толкова дълго време е напълно позволено да бъде със същия размер като цяло число,
и тя също може да бъде със същия размер като дълго.
И то просто така се случва, е, че в 99,999% на системи, ще бъде равна на
Int или дълго. Просто зависи на 32-битова или 64-битова. >> Студент Добре.
В плува, как е десетичната точка, определена по отношение на бита?
Както двоичен? >> Да.
Не е нужно да знаете, че за CS50.
Ти дори не научаваме, че през 61.
Вие не научат, че наистина всеки курс.
Това е просто представителство.
Забравя точните разпределения битови.
Идеята на числа с плаваща запетая е, че отделят определен брой битове да представлява
По принцип, всичко е в научна нотация.
Така разпределят определен брой битове да представлява самия номер, както и 1,2345.
Аз никога не може да представлява число с повече цифри, отколкото 5.
След това можете също така да определи специален броя на битовете, така че тя е склонна да бъде като
можете да отидете до определен брой, като това е най-големият експонат можете да имате,
и можете да слизат само до известна експонат
искал, че е най-малкият експонат можете да имате.
>> Не си спомням точните бита начина, по който се отнасят към всички тези ценности,
но определен брой битове са посветени на 1.2345,
друг определен брой битове са посветени на експонентата,
и това е само възможност да се покаже изразител на определен размер.
[Ученик] и двойно? Е, че като допълнително пердашка? >> Да.
Това е едно и също нещо като плувка, освен сега сте с 8 байта, вместо на 4 байта.
Сега вие ще бъдете в състояние да използват девет цифри или 10 цифри,
и това ще бъде в състояние да отиде до 300 вместо 100. >> Студент Добре.
И плува също са 4 байта. >> Да.
Е, пак вероятно зависи като цяло на общото изпълнение,
но плувки са 4 байта, двойки са 8.
Двойки се наричат ​​двойно, защото те са два пъти размера на плувката.
[Ученик] Добре. И има двойно удвоява? >> Няма.
Мисля >> студент като дълги чак? >> Да. Не мисля. Да.
[Ученик] На тест миналата година имаше въпрос за основната функция
да бъде част от вашата програма.
Отговорът беше, че тя не трябва да бъде част от вашата програма.
В каква ситуация? Това е, което видях.
[Bowden Изглежда - >> [ученик] Каква ситуация?
Имате ли проблем? >> [Ученик] Да, определено може да го издърпайте.
То не трябва да бъде технически, но по същество това ще бъде.
[Ученик] видях една за друга година.
Беше като вярно или невярно: Валиден - >> О, в файл.?
[Ученик] Всеки в файл трябва да има [както говори наведнъж - неразбираем]
Добре. Така че това е отделно.
>> В файл просто трябва да съдържа функции.
Можете да съставят досие в машинен код, двоичен, независимо,
без да е изпълним все още.
Валиден изпълним трябва да имат основна функция.
Можете да напишете 100 функции в 1 файл, но не и основните
и след това съставят, че в двоичен,
след това ти пишеш друг файл, който има само основната, но го нарича един куп от тези функции
в този двоичен файл тук.
И така, когато сте прави изпълнимия файл, това е какво линкерът
се съчетава тези две двоични файлове в един изпълним.
Така че в файл не трябва да има водеща функция на всички.
И на големи бази код ще видите хиляди файлове в и 1 главния файл.
Още въпроси?
[Ученик] е друг въпрос.
В него се казва, да е компилатор. Вярно или невярно?
И отговорът е невярна, и аз разбрах, защо не е като да звъня.
Но това, което ние наричаме направи, ако не е?
Уверете се, е просто - да видим какво точно го нарича.
Но той просто работи команди.
Уверете.
Мога да се справим с това. Да.
О, да. Уверете се също прави това.
Това казва, че целта на марката полезност е да се определи автоматично
които трябва да бъдат прекомпилирани парчета от по-голяма програма
и да издава команди, за да ги компилирате.
Можете да направите файлове, които са абсолютно огромен.
Уверете се гледа на печати на файлове и, както казахме и преди,
можете да компилирате отделни файлове, и това не е докато не стигнем до свързващата програма
че те са поставени заедно в един изпълним.
Така че, ако имате 10 различни файлове и да направите промяна на 1 от тях,
тогава какво правят ще направи е само прекомпилирате, че един файл
и след това relink всичко заедно.
Но това е много по-тъп от това.
Това е до вас напълно да се определи, че това е това, което трябва да се прави.
Тя по подразбиране има способността да разпознават тези неща на времето за печат,
но можете да напишете файл марката да правите нищо.
Можете да напишете направи файл, така че, когато напишете просто CD в друга директория.
Бях разочарован, защото аз халс всичко вътре на моята техника
и тогава ще видите на PDF от Mac.
>> Така че аз Finder и мога да направя Отиди, да се свърже със сървъра,
и сървъра се свържа с моята техника, а след това отваряне на PDF
, които получава, съставен от латекс.
Но аз бях разочарован, защото всеки път, необходима за опресняване на PDF,
Аз трябваше да го копирате в определена директория, че могат да имат достъп
и ставаше досадно.
Така че, вместо да пише марката файл, който вие трябва да определите как прави нещата.
Как да направите това е PDF LaTeX.
Просто като всеки друг файл на марката - Предполагам, че не сте виждали направят файловете,
но ние имаме в уреда глобалния файл марка, които просто казва,
Ако компилирате файл C, използвайте звъня.
И така, ето на ми марка файл, че правя аз казвам,
този файл, вие ще искате да компилирате с PDF LaTeX.
И така, това е PDF LaTeX, което прави събирането.
Уверете се, не е компилиране. Това е просто тези команди в последователността, която съм посочил.
Така той работи PDF LaTeX, той го копира в директорията, аз искам да се копират,
тя CD в директорията и други неща,
но всичко, което прави, е да признае, когато файлът промени,
и ако тя се променя, а след това тя ще изпълнява командите, които е трябвало да се движи
Когато файлът промени. >> Студент Добре.
Аз не знам къде глобалните файлове марката са за мен да го проверите.
Други въпроси? Нещо от миналото викторини? Всички показалецът неща?
Има фините неща с указатели като -
Аз няма да бъде в състояние да намери въпрос викторина върху него -
но точно като този вид на нещо.
Уверете се, че сте разбрали, че когато казвам Int * X * Y -
Това не е точно нищо тук, предполагам.
Но като * X * Y, това са две променливи, които са в стека.
Когато казвам х = изчистване (sizeof (INT)), х е променлива в стека,
изчистване някои Блокиране на куп, и ние сме като х точка на куп.
>> Значи нещо в стека точки на куп.
Когато ви изчистване нищо, вие неизбежно съхранение вътрешността на показалеца.
Така че показалецът е на стека, malloced блок е на куп.
Много хора се объркват и да кажа, вътр * х = изчистване х е на куп.
Не. Какво х посочва е на куп.
х само по себе си е на стека, освен ако по някаква причина сте х глобална променлива,
в такъв случай тя се случва да бъде в друг регион на паметта.
Така че следенето, тези кутия и стрела диаграми са доста често срещано за теста.
Или, ако това не е на викторина 0, той ще бъде на викторина 1.
Трябва да знаете, всички тези стъпки при съставянето
, тъй като трябваше да отговори на въпросите на тези. Да.
[Ученик] Можем ли да отидем тези стъпки - >> Разбира се.
Преди стъпки и съставяне имаме предварителна обработка,
съставянето, монтаж и свързване.
Предварителна обработка. Какво правим?
Това е най-лесният стъпка по - добре, а не като
това не означава, че трябва да е очевидно, но това е най-лесният стъпка.
Вие може да се приложи. Да.
[Ученик] Вземете това, което имате във вашия включва по този начин и го копира и след това да определя.
Изглежда за неща като # включват и # определят,
и то само копия и пасти за какво действително означава.
Така че, когато казват, # включват cs50.h, предпроцесорни копиране и поставяне cs50.h
в тази линия.
Когато казвате # определят Х да бъде 4, предпроцесорни минава през цялата програма
и замества всички случаи на х 4.
Така че предпроцесорни валиден файл C и извежда валиден файл C
, където нещата са били копирани и поставили.
Така че сега компилиране. Какво правим?
[Ученик] от С до двоичен.
>> [Bowden] То не отива по целия път до двоичен.
[Ученик] машинен код, след това? >> Това не е машинен код.
[Ученик] събрание? >> Събрание.
Отива на събрание, преди да премине целия път до код C,
и на повечето езици направя нещо подобно.
Вземете който и език от високо ниво, и ако ти започваш да го компилирате,
това е вероятно да се събират в стъпки.
Първо, че ще съставят Python 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 не е всъщност O файл, но това е достатъчно близо, че няма фундаментална разлика.
Така че свързването просто носи куп файлове
, който поотделно да съдържа всички функции, трябва да използвам
и създава изпълним, които действително ще работи.
>> И така, това е също това, което ние казвахме преди
, където можете да изпиете 1000 в файлове, компилирането на всички тях. о файлове,
което вероятно ще отнеме известно време, а след това промените 1 в файл.
Трябва само да компилирате, че една в файл и след това relink всичко останало,
свържете всичко обратно.
[Ученик] Когато се свързвате пишем lcs50?
Да, така lcs50. Този флаг сигнали към свързващата програма, която трябва да свързва в тази библиотека.
Въпроси?
Ли сме преминали над двоичен, различни от тези 5 секунди в първата лекция?
Не мисля.
Трябва да знаете, всички на големия Os, че ние сме отишли,
и трябва да бъде в състояние да, ако ви дадохме функция,
трябва да бъде в състояние да кажа, че е голяма O, грубо. Или добре, Big O е груб.
Така че, ако видите вложени за вериги примка през същия брой неща,
като Int аз, аз <N; Int J, J > [ученик] квадрат. >> Тя е склонна да бъдат н квадрат.
Ако сте тройно вложен, тя е склонна да бъде N кубчета.
Така че такива неща трябва да бъде в състояние да посочи веднага.
Трябва да знаете, вмъкване вид и сортиране балон и се сливат сортиране и всички тези.
Това е по-лесно да се разбере защо те са тези, които са N на квадрат и N дневник - и всичко това
защото аз мисля, че имаше викторина една година, когато основната ви даде
изпълнението на балон вид и каза: "Какво е времето за изпълнение на тази функция?"
Така че, ако го признае като балон вид, тогава може веднага да кажа н квадрат.
Но ако просто го поглеждам, не е необходимо дори да осъзнае, че е вид балон;
може просто да се каже, това прави това и това. Това е N на квадрат.
[Ученик] Има ли някакви трудни примери, които може да излезе с
като подобна идея разберете?
>> Аз не мисля, че ще ви даде всички трудни примери.
Нещо балон вид е толкова трудно, колкото ние ще отидем,
и дори, че толкова дълго, колкото разбирам, че сте итерации над масива
за всеки елемент в масива, което ще бъде нещо, което е N квадрат.
Има общи въпроси, като тук имаме - О.
Само онзи ден, Дъг твърди, "Аз съм измислил алгоритъм, който да сортирате масив
"На N числа в O (дневник н) време!"
Е, как да знаем, че е невъзможно?
[Чува студент отговор] >> Да.
Най-малкото, трябва да се докосне всеки елемент в масива,
така че е невъзможно да сортирате масив -
Ако всичко е в несортирани ред, тогава започваш да се докосват всичко в масива,
така че е невъзможно да го направи за по-малко от О на N.
[Ученик] ни показа, че пример за това е в състояние да го направя в O на н
ако използвате много памет. >> Да.
И това е - да забравя какво това е. - го брои вид?
Хмм. Това е цяло число алгоритъм за сортиране.
Търсех специално име за това, че не можеше да си спомни миналата седмица.
Да. Това са видове сортове, които могат да изпълнят нещата в Big O N.
Но има ограничения, като можете да използвате само числа до определен брой.
Плюс това, ако се опитвате да сортирате нещо, това е. -
Ако масив е 012, -12, 151, 4 милиона,
тогава, че един елемент е напълно да съсипе цялата сортиране.
>> Въпроси?
[Ученик] Ако имате рекурсивна функция и тя просто прави рекурсивни повиквания
в отчета за връщане, това е опашката рекурсивен,
и така, че не би да използват повече памет по време на изпълнение
или най-малко, че ще използват сравнима памет като повтарящ решение?
[Bowden Да.
Тя вероятно ще бъде малко по-бавно, но не съвсем.
Опашката рекурсивен е доста добър.
Поглеждайки отново към стека рамки, нека кажем, че имаме основната
и ние имаме INT бар (INT х) или нещо.
Това не е идеалното рекурсивна функция, но връщане бар (х - 1).
Така че, очевидно, това е погрешна. Трябва базови случаи и неща.
Но идеята тук е, че това е опашката рекурсивен,
което означава, че когато основният бар разговори ще получи рамката му стак.
В тази стека рамка ще бъде малко блок на паметта
, който съответства на своя аргумент х.
И така, нека да кажем, че основната случва да се обадя бар (100);
Така ще започне като 100 х.
Ако компилаторът разпознава, че това е опашката рекурсивна функция,
тогава, когато бар рекурсивно повикване до бар
вместо да правят нова рамка комин, който е мястото, където стека започва да се разраства главно,
в крайна сметка тя ще върви в купчината и след това да получите segfaults
защото паметта започва сблъсък.
>> Така че, вместо да направи своя собствена рамка стека, тя може да реализира,
хей, аз никога не съм наистина трябва да се върнем към тази стека рамка,
така че вместо това просто ще замени този аргумент с 99 и след това да започне бар навсякъде.
И тогава ще го направя отново и ще стигне бар връщане (х - 1),
и вместо да правят нова рамка стак, той просто ще замени сегашната си аргумент с 98
и след това скочи обратно към самото начало на бара.
Тези операции, заменяйки стойност на един стек, че едно и скачане обратно в началото,
са доста ефективни.
Така че не само това е същото използването на памет като отделна функция, която е повтаряща се
защото сте се използват само 1 стак рамка, но не сте страда от недостатъци
налага да се обадя функции.
Функции на повикване може да бъде доста скъпо, защото трябва да направим всичко това за настройка
и teardown и всички тези неща.
Така че това опашката рекурсия е добро.
[Ученик] Защо не го създадете нови стъпки?
Защото тя осъзнава, че не е необходимо.
Призивът за бар е просто връщане на рекурсивно повикване.
Така че не трябва да правя нещо с върнатата стойност.
Просто ще го върне веднага.
Така че просто ще замени своя аргумент и да започнете отначало.
И също така, ако не са на опашката рекурсивна версия,
след това можете да получите всички тези ленти, когато този бар се връща
тя трябва да се върне стойността си до това, че бар веднага се връща
и го връща стойността си до тази, то тогава просто ще връщат незабавно
и да се върнете стойността си за този.
Значи запазите тази пръкват всички тези неща на стека
от завръщането стойност е просто ще бъдат прехвърлени по целия път обратно до така или иначе.
Така че защо не просто да замени нашия спор с актуализираната аргумент и да започнете отначало?
Ако функцията не е опашка рекурсивен, ако направи нещо подобно -
[Ученик], ако бар (X + 1). >> Да.
>> Така че, ако го сложите в състояние, тогава правиш нещо с върнатата стойност.
Или дори ако просто се връщат 2 * бар (х - 1).
Така че сега бар (х - 1) трябва да се върне, за да се изчисли два пъти тази стойност,
така че сега тя се нуждае от свой отделен кадър стека,
и сега, без значение колко трудно се опитате, вие ще трябва да
Това не е опашка рекурсивна.
[Ученик] Ще се опитам да донесе рекурсия да се стремят към опашката рекурсия -
Bowden] В един идеален свят, но в CS50 не е нужно.
За да получите рекурсия опашката, като цяло, създаде допълнителен аргумент
бар ще се INT х г.
и у съответства на крайния нещо, което искате да се върнете.
Тогава започваш да се върне бар (х - 1), 2 * Y.
Така че това е просто най-високо равнище как да трансформирате нещата да са на опашката рекурсивно.
Но допълнителен аргумент -
И след това в края на краищата, когато стигнете до вашата база случай, просто се върнете у
защото сте били натрупване през цялото време на връщане стойността, която искате.
Някак си са го прави итеративно, но се използват рекурсивни повиквания.
Въпроси?
[Ученик] Може би за аритметика на показалеца, като при използване на струните. >> Разбира се.
Pointer аритметика.
При използване на струните е лесно, защото струните са харак звезди,
символа са завинаги и винаги един байт,
и така показалеца аритметиката е еквивалентно на редовно аритметика, когато имаш работа със струни.
Нека просто кажем, Чар * = "здравей".
Така че ние имаме един блок в паметта.
Той се нуждае от 6 байта, тъй като винаги се нуждаят от нула терминатор.
Чар * и ще отбележи началото на този масив.
Така и точки там.
Сега, това е основно как работи всеки масив,
независимо от това дали тя е връщане с изчистване или дали това е в стека.
Всеки масив по същество е указател към началото на масива,
и тогава всеки масив работа, всеки индексиране, е просто да навлизам в този масив определен компенсира.
>> Така че, когато казвам нещо като [3]; това ще и се брои три символа.
Така че [3], имаме 0, 1, 2, 3, така че [3] ще се отнасят до този л.
[Ученик] И ние може да достигне същата стойност като S + 3 и скоби звезда?
Да.
Това е еквивалентно на * (+ 3);
и това е завинаги и винаги равностойни, без значение какво правиш.
Вие никога не трябва да се използват синтаксиса на скоба.
Винаги можете да използвате * (S + 3) синтаксис.
Хората са склонни да харесват синтаксиса скоба, все пак.
[Ученик] Така всички масиви всъщност са само указатели.
Има малка разлика, когато казвам, Int [4]; >> студент ли това, че създава паметта?
[Bowden] Това ще създаде четири цели числа на стека, така че 16 байта като цяло.
Това ще създаде 16 байта в стека.
х не се съхранява никъде.
Това е просто символ, отнасящи се до началото на нещо.
Защото обяви масив в рамките на тази функция,
какво компилатор ще направя, е просто да замени всички случаи на променливата х
, когато се случи да изберете да поставите тези 16 байта.
Той не може да направи това с Чар *, защото е действително показалеца.
Той е свободен след това да сочи към други неща.
х е константа. Вие не може да го насочите към друг масив. >> Студент Добре.
Но тази идея, тази индексиране, е един и същ, независимо от това дали тя е традиционна масив
или ако това е указател към нещо или ако това е указател към malloced масив.
И в действителност, това е толкова равностойна, че това е едно и също нещо.
То всъщност само се превежда това, което е вътре в скобите и това, което е останало от скобите,
добавя заедно, и dereferences.
Така че това е също толкова валиден както * (S + 3) или S [3].
[Ученик] Може ли да има указатели, сочещи към 2-измерни масиви?
>> Това е по-трудно. Традиционно, не.
2-мерен масив е само едно-мерен масив с някои удобен синтаксис
защото, когато казвам, вътр [3] [3], това наистина е само на 1 масив с 9 стойности.
И така, когато аз индекс, компилаторът знае какво имам предвид.
Ако кажа, че [1] [2], той знае, че аз искам да отида на втория ред, така че ще пропуснете първите 3
и след това го иска второто нещо в това, така че ще се получи това.
Но това все още е само един-мерен масив.
И така, ако исках да присвоите указател към този масив,
Бих казал, Int * р = X;
Тип Х е просто -
Това е грубо казва на х, тъй като тя е просто символ и това не е действително променлива,
но това е само едно цяло число *.
х е само указател към началото на тази. >> Студент Добре.
И така, аз няма да имат достъп до [1] [2].
Мисля, че има специален синтаксис за деклариране на указател,
нещо нелепо като Int (* [- нещо абсолютно нелепо аз дори не знам.
Но има синтаксис за деклариране на указатели като със скоби и други неща.
Той дори не може да ви позволи да направите това.
Мога да погледна назад към нещо, което ще ми кажеш истината.
Аз ще го търсим по-късно, ако има синтаксис за точка. Но вие никога няма да го видим.
И дори синтаксисът е толкова архаичен, че ако го използвате, хората ще бъдат объркани.
Многомерни масиви са доста редки, тъй като това е.
Почти -
Е, ако правиш матрични неща не ще да са рядкост,
но в C, че рядко ще се използват многомерни масиви.
Да. >> [Ученик] Да кажем, че имате един наистина дълъг масив.
>> Така че в виртуалната памет ще се появи за да бъде всичко поред,
както и елементите, които са в непосредствена близост един до друг,
но във физическата памет, ще бъде възможно за това да се раздели? >> Да.
Как работи виртуалната памет е просто разделя -
Единица на разпределение е страница, която има тенденция да бъде 4 килобайта,
и така, когато казва процес, хей, аз искам да се използва тази памет,
операционната система ще го разпределят по 4 килобайта за този малък блок от памет.
Дори ако използвате само един байт в целия блок от паметта,
операционната система ще го дам 4 килобайта.
И така, какво означава това е, може да има - нека да кажем, че това е моят стак.
Това стека могат да бъдат разделени. Стака ми може да бъде мегабайти и мегабайта.
Моят стека може да бъде огромен.
Но самият стак трябва да бъде разделена на отделни страници,
ако погледнем тук нека кажем, че това е нашата RAM,
ако имам 2 гигабайта RAM, това е настоящ адрес 0 като zeroth байт на моята RAM,
и това е 2 гигабайта целия път тук.
Така тази страница може да съответства на този блок тук.
Тази страница може да съответства на този блок тук.
Това може да съответства на този тук.
Така че операционната система е да зададете физическа памет
на всяка отделна страница произволно.
А това означава, че ако тази граница се случва да бъдат отнесени към масив,
масив се случва да бъдат оставени на това и правото на този ред на страницата,
този масив ще бъде разделен на физическата памет.
И тогава, когато спиране на програмата, когато процесът приключи,
тези преобразувания се изтриват и след това е свободен да използва тези малки блокове за други неща.
Още въпроси?
[Ученик] показалеца аритметика. >> О, да.
Струните са по-лесни, но търся нещо като цели числа,
Така че обратно към Int [4];
Дали това е масив или дали това е указател към malloced масив от 4 числа,
ще се третират по същия начин.
[Ученик] Така масиви са на куп?
[Прекъснати] Масивите не са на куп. >> Студент О
>> [Bowden] Този тип масив има тенденция да бъде в стека
освен ако не го декларират в игнориране на глобални променливи. Да не се използват глобални променливи.
Вътре функция казвам Int [4];
Това ще създаде четири цяло блок на стека за този масив.
Но това изчистване (4 * sizeof (INT)); ще отиде на куп.
Но след този момент мога да използвам х и п почти по същия начин,
други от изключенията казах преди около вие можете да присвоите стр..
Технически, техните размери са малко по-различен, но това е напълно без значение.
Вие всъщност никога не използват техните размери.
Стр. мога да кажа, [3] = 2, или [3] = 2;
Можете да ги използвате по точно същия начин.
Така на показалеца аритметика - Да.
[Ученик] Не трябва ли да се направи п * ако имате скобите?
В скоби са имплицитно и сочен. >> Добре.
Всъщност, това, което казваш с можете да получите многомерни масиви
с указатели, какво можете да направите, е нещо като, да речем, вътр ** п = изчистване (sizeof (INT *) * 5);
Аз просто ще пиша всичко това първо място.
Аз не искам това.
Добре.
Това, което направих тук е - Това трябва да бъде п [I].
Така процентни пункта е указател към указател.
Вие mallocing п да сочи към масив от 5 INT звезди.
Така че в памет имате в стека стр.
Това ще да сочи към масив от 5 блока, които са всичко от себе си указатели.
И тогава, когато аз изчистване тук, изчистване, че всяка от тези отделни насоки
трябва да сочи към отделен блок от 4 байта на куп.
Така че това пункта до 4 байта.
И тази пункта до различни 4 байта.
>> И всички те сочат към собствените си 4 байта.
Това ми дава начин за правене на многоизмерните неща.
Мога да кажа, PP [3] [4], но сега това не е едно и също нещо като многомерни масиви
тъй като многомерни масиви го преведе [3] [4] в един отместване в масива х.
Това dereferences стр., достъп до трети индекс, след това dereferences
и достъп - 4 ще са невалидни - втория индекс.
Като има предвид, че когато имахме Int [3] [4] преди като многомерен масив
и когато щракнете двукратно скоба това е наистина само един сочен,
сте след един показалеца и след това компенсира,
това е наистина 2D препратки.
Следват две отделни указатели.
Така че това също технически ви позволява да имате многомерни масиви
където всеки отделен масив е с различни размери.
Така че аз мисля, назъбени многомерни масиви е това, което се нарича
тъй като първото нещо, което наистина може да посочи нещо, което има 10 елемента,
Второто нещо, което може да посочи нещо, което има 100 елемента.
[Ученик] Има ли ограничение за броя на указатели, които могат да имат
сочещи към други указатели? >> Бр.
Можете да имате INT ***** стр..
Обратно към показалеца аритметика - >> [ученик] О >> Да.
[Ученик] Ако имам вътр *** стр. и тогава аз правя dereferencing и казвам стр. * е равна на тази стойност,
е само да се направи на 1 ниво на dereferencing? >> Да.
Така че, ако искате да получите достъп до нещо, което последния показалеца сочи към
Тогава *** стр.. >> Добре.
Така че това е п пункта до 1 блок, посочва друг блок, посочва друг блок.
Тогава, ако правиш * р = нещо друго, тогава ще се променят тази
до сега сочи към друг блок. >> Добре.
>> [Bowden] И ако те са били malloced, тогава вече изтече памет
освен ако не се случи да има различни справки от тези
тъй като не мога да се върна към онези, които просто изхвърлих.
Pointer аритметика.
Int [4]; ще разпредели масив от 4 числа
където Х е да сочи към началото на масива.
Така че, когато казвам нещо подобно [1]; Искам да означава, отидете на второто число в масива,
което ще бъде това.
Но наистина, това е 4 байта в масива, тъй като това число заема 4 байта.
Така с отместване на една наистина означава компенсиране на 1
пъти по-голяма независимо от типа на масива.
Това е масив от цели числа, така че знае как да направи 1 пъти размера на вътр когато иска да компенсира.
Другият синтаксис. Не забравяйте, че това е еквивалентно * (X + 1);
Когато казвам показалеца + 1, който се връща е адресът, че показалецът е съхраняване
плюс милион пъти по-голяма от вида на показалеца.
Така че, ако х = ox100, тогава х + 1 = ox104.
И вие можете да злоупотребяват с това и да кажа нещо подобно Чар * C = (Чар *) х;
и сега в ще бъде на същия адрес като х.
в ще бъде равна на ox100,
но в + 1 ще бъде равна на ox101
тъй като аритметика на показалеца зависи от вида на показалеца, които се добавят към.
Така че в + 1, изглежда в, това е знак показалеца, така че ще да добавите 1 пъти размера на Чар,
който винаги ще да бъде една, така че да получите 101,
като има предвид, че ако го направя Х, който е все още 100 х + 1 ще бъде 104.
[Ученик] Можете ли да използвате C + +, за да преминете показалеца от един?
Да, можете.
Вие не можете да направите това с Х, защото х е просто символ, тя е постоянна, не можете да променяте х.
>> Но в се случва, за да бъде само показалеца, така че C + + е напълно валидна и ще увеличите с 1.
Ако бяха само в едно цяло число *, а след това C + + ще бъде 104.
+ + Показалеца аритметика точно както в + 1 би направил показалеца аритметика.
Това е всъщност колко много неща като вид сливане
Вместо да създава копия на неща, може вместо това да мине -
Както и ако исках да преминат половина на масива - нека да изтриете някои от това.
Да кажем, че съм искал да предаде тази част на масива във функция.
Какво щях да преминат към тази функция?
Ако минавам х, много съм този адрес.
Но аз искам да мине този конкретен адрес. И така, какво трябва да мине?
[Ученик] Pointer + 2?
[Bowden] Така х + 2. Да.
Това ще бъде този адрес.
Вие също така много често го виждам като [2] и след това адреса на този.
Така че трябва да се вземат адреса от него, защото скобата е косвена и сочен.
[2] се отнася до стойност, която е в тази клетка, и след това искате адреса на тази кутия,
Значи вие казвате, и [2].
Така че това е как нещо в нещо се сливат, където искате да мине половината от списъка на нещо
Наистина ли просто минават и [2], и сега като рекурсивния покана се отнася,
ми започва нов масив.
Последно въпроси минути.
[Ученик] Ако не сложи амперсанд или - какво е това? >> Звезда?
[Ученик] Star. >> Технически, сочен оператор, но - >> [ученик] и сочен.
>> Ако не сложите звезда или амперсанд, какво ще стане, ако просто кажем, Y = X и X е указател?
Какъв е типът на у? >> Студент аз просто ще кажа, че е показалеца 2.
Така че, ако просто кажем, Y = X, сега х и у точка за едно и също нещо. >> [Ученик] Точка на едно и също нещо.
И ако х е INT показалеца? >> Той ще се оплакват, защото не можете да присвоите указатели.
[Ученик] Добре.
Не забравяйте, че указатели, макар и да ги привлече като стрели,
наистина всичко, магазин Int * X - наистина всичко х съхранение нещо подобно ox100,
, които се случи да се представят като сочи към блока, се съхраняват при 100.
Така че, когато казвам, вътр * Y = X; аз просто копиране ox100 в г.,
които ние просто ще се представят като у също сочи към ox100.
И ако кажа, вътр I = (INT) х, тогава аз ще се съхранява независимо от стойността на ox100
вътре в нея, но сега ще трябва да се тълкува като цяло число, а на показалеца.
Но имате нужда от гласове, или в противен случай ще се оплакват.
[Ученик] Така че, искаш да кажеш да хвърли
Дали тя ще бъде леене вътр на Х или леене вътр на у?
[Bowden] Какво?
[Ученик] Добре. След тези скоби е там ще бъде една Х или може там?
>> [Bowden]. х и у са еквивалентни. >> Студент Добре.
Тъй като и двамата са указатели. >> Да.
[Ученик] Така че ще съхранява шестнадесетична 100 в цяло число форма? >> Bowden Да.
Но не и стойността на каквото и да посочва.
[Bowden Да. >> [Ученик] Така че просто адрес в целочислен форма. Добре.
[Bowden] Ако искаш по някаква странна причина,
изключително биха могли да се справят с указатели и никога не се справят с числа
и да бъде само като Int * х = 0.
Тогава започваш да се получи много объркана веднъж показалеца аритметика започва да се случва.
Така че номерата, които те складират са безсмислени.
Това е просто начина, по който в крайна сметка да ги интерпретира.
Така че аз съм свободен да копирате ox100 от INT * на вътр
и аз съм свободен да присвоите - Ти си най-вероятно ще се развика, за това, че не леене
Аз съм свободен да присвоите нещо подобно (INT *) ox1234 в тази произволна * вътр.
Така ox123 е също толкова валиден адрес на памет, както е и у.
Г. се случва да се върне нещо, което е доста ox123.
[Студент би това е един наистина страхотен начин да отида от шестнадесетичен десетичен вид,
хареса, ако имате показалец и го хвърли като Int?
[Bowden Вие наистина може да печатате, като използвате като ФОРМАТ.
Да кажем, че имам Int Y = 100.
Така ФОРМАТ (% г \ N - както би трябвало вече да знаят - отпечатване, че като цяло число, X%.
Ние просто ще го отпечатате като шестнадесетичен.
Така че показалецът не се съхранява като шестнадесетичен,
и цяло число не се съхранява като знак след десетичната запетая.
Всичко се съхранява като двоични.
Това е просто, че ние сме склонни да показват указатели като шестнадесетичен
защото мислим за неща в тези 4-байтови блокове,
и адреси от паметта са склонни да бъдат запознати.
Ние сме като, ако тя започва с BF, а след това се случи да бъде в стека.
Така че това е само нашата интерпретация на указатели като шестнадесетичен.
Добре. Някакви последни въпроси?
>> Аз ще бъда тук за малко, след като, ако имате нещо друго.
И това е края на този.
>> [Ученик] Ура! [Аплодисменти]
>> [CS50.TV]