[Powered by Google Translate] [第4節 - 更舒適]
[羅布·鮑登 - 哈佛大學]
[這是CS50。 - CS50.TV]
我們明天有一個測驗，如果你們不知道。
它基本上是你能看到在課堂上或在課堂上所看到的一切。
這包括指針，即使他們是一個非常新的主題。
你至少應該深入了解他們的高水平。
凡是過去在課堂上，你應該了解的測驗。
所以，如果你有問題了，你可以問他們。
但是，這將是一個非常學生主導的會議，你們問的問題，
所以我希望人們有很多疑問。
有沒有人有問題嗎？
是。 >> [學生]你能對指針呢？
我就去了指針。
所有的變量一定住在內存中，
但通常你不擔心你剛才說X + 2和y + 3
編譯器將找出的東西都在那裡生活。
當你正在處理的指針，現在你顯式地使用這些內存地址。
因此，一個單一的變量將永遠只住在任何給定的時間在一個單一的地址。
如果我們想聲明一個指針，類型是什麼的樣子？
>> 我要聲明一個指針p。的類型是什麼樣子呢？
[學生] * P。 >>呀。所以int * p。
我怎樣才能使它指向為x？ >> [學生]連字號。
鮑登]符號是真正的被稱為運營商的地址。
所以當我說＆X變量x的內存地址。
所以現在我有指針p，在我的代碼中的任何地方，我可以使用* P
我也可以用x，這將是完全一樣的東西。
（* P）。這是什麼做的嗎？這是什麼明星是什麼意思？
[學生]是指在該點的值。 >>呀。
因此，如果我們看它，它可以是非常有用的，畫出來的圖
這是一個小方塊的記憶，而這恰好為x值4，
然後我們有一個小盒子，內存為P，
，因此P點為x，所以我們畫一個箭頭從p到x。
所以，當我們說我們說* P框，即p。
星是按照箭頭，然後做你想做的那個盒子在那裡。
因此，我可以說，* P = 7;將去框，x和變化，7。
或者，我可以說Z = * P * 2，這是令人困惑，因為它的明星，明星。
一星級提領P，其他明星乘以2。
請注意，我可以有一樣好更換用x * P。
您可以使用它們以同樣的方式。
再後來我可以有p指向一個完全新的東西。
我只能說，P = &z;
所以，現在P沒有再久點為x，它指向到z。
任何時候，我做* P一樣做Ž。
因此，有用的事情是，一旦我們開始進入功能。
>> 聲明一個指針，它指向的東西，這是一種無用的
然後你只提領
時，你也可以使用原來的變量開始。
但是，當你進入功能 - 讓我們說，我們有一些功能，詮釋富，
需要一個指針，* p = 6;
就像我們之前看到的掉期，你不能做一個有效的交換和一個單獨的函數
只是路過，因為一切都在C總是按值傳遞的整數。
即使當你通過指針是按值傳遞的。
碰巧的是，這些值是內存地址。
所以當我說富（P）;我的指針傳遞到函數foo
然後foo是做* P = 6;
所以裡面的函數，* p是等價於x，
但我不能使用x裡面的這個函數該功能，因為它不是範圍之內。
因此，* p = 6是唯一的出路，我可以訪問另一個函數的局部變量。
或者，指針是唯一的出路，我可以訪問另一個函數的局部變量。
[學生]：比方說，你想返回一個指針。你究竟是如何做到這一點？
[鮑登]返回一個指針的東西，如int y = 3的回報＆Y？ >> [學生]是啊。
鮑登]好吧。你不應該這樣做。這是不好的。
我想我看到了在這些演講的幻燈片，你開始看到這個圖的內存
在這裡，你有內存地址0
在這裡你有內存地址4演出或2到32。
那麼，你已經得到了一些東西，有些東西，然後你有你的堆棧
你有你的堆，你剛開始學習，長大了。
[學生]是不是在堆上面的堆棧？
>> 是啊。堆在上面，不是嗎？ >> [學生]好了，他把0之上。
[學生]：哦，他把0之上。 >> [學生]：哦，好吧。
免責聲明：Anywhere與CS50你要這樣看。 >> [學生]好吧。
只是，當你第一次看到棧，
就像當你想到一個堆棧，你認為彼此頂部堆放的東西。
因此，我們傾向於翻轉左右，所以堆棧的增長就像一個堆棧通常會
代替堆棧垂下。 >> [學生]不要堆技術上長大過，雖然？
這取決於你的意思是長大了。
堆和棧的增長方向相反。
棧是在不斷增長，在這個意義上，它的成長過程
朝著更高的內存地址和堆增長
在它的增長向低內存地址。
因此，頂端是0和底部是高的存儲器地址。
他們兩人都不斷增長，只是在相反的方向。
[學生]：我剛才只是說，因為你說你把堆棧的底部
因為它的堆棧看起來更直觀，因為在堆的頂部開始，
堆的本身上，所以that's - >>呀。
你也覺得長大了，大的堆空間，但堆棧如此。
因此，堆棧是一個樣的，我們要展現長大的。
但是無論你看，否則會顯示地址0頂部
和最高的內存地址的底部，所以這是你的內存通常的看法。
>> 你有問題嗎？
[學生]：你能告訴我們更多的堆？
是啊。我會在第二。
首先，要追溯到為什麼返回＆Y是一件壞事，
在棧上，你有一堆的棧幀代表所有的功能
已被調用。
因此，忽略以前的事情，你的堆棧的頂部總是要的主要功能
因為這是第一個函數的調用。
然後當你調用另一個函數的堆棧是怎麼回事增長下降。
所以，如果我調用一些函數，foo和它得到它自己的堆棧幀，
它可以調用一些函數，酒吧，它得到它自己的堆棧幀。
和酒吧可以是遞歸的，它可以調用本身，
等第二次調用酒吧是會得到它自己的堆棧幀。
因此，這些堆棧幀的局部變量
和所有的功能參數 -
此功能是在本地範圍內的任何事情，這些堆棧幀。
因此，這意味著當我說像酒吧是一個函數，
我只是要聲明一個整數，然後返回一個指針，該整數。
Ÿ生活？
[學生] Y住在酒吧。 >> [鮑登]是啊。
在這個小廣場的內存的某個地方，是一個較小的廣場，有Y。
當我返回＆Y，我返回一個指針，這個小的內存塊。
但後​​來當函數返回時，它的堆棧幀被彈出堆棧。
這就是為什麼它被稱為堆棧。
這是堆棧的數據結構，如果你知道那是什麼。
甚至像一個托盤堆疊的例子，
主要是要去的底部，然後你調用的第一個函數是要去最重要的是，
，你可以回到主，直到返回的所有功能，被稱為
已放置在它上面。
>> [學生]所以，如果你做返回該值是Y，如有更改，恕不另行通知。
是的，it's - >> [學生]會被覆蓋。 >>呀。
這是完全 - 如果你嘗試 -
這也將是一個int *吧，因為它返回一個指針，
因此它的返回類型是int *。
如果您嘗試使用這個函數的返回值，這是不確定的行為
因為指針所指向壞的內存。 >> [學生]好吧。
那麼，如果，例如，你宣布INT * Y = malloc的（如sizeof（int））？
這是更好的。是。
[學生]當我們談到如何將事情拖到我們的回收站
他們實際上沒有被刪除，我們只是失去它們的指針。
因此，在這種情況下，我們實際上是刪除值是它在內存中仍然存在？
對於在大多數情況下，它會仍然存在。
但是，讓我們說，我們碰巧調用一些其他的功能，巴茲。
巴茲在這裡會得到它自己的堆棧幀。
這將覆蓋所有的這些東西，
然後如果你稍後嘗試和使用的指針，你有，
它不會是相同的值。
它已經改變了，只是因為你調用該函數巴茲。
[學生]，但我們沒有，我們仍然可以得到3？
鮑登在所有的可能性，你會的。
但你不能依靠這一點。 Ç只是說未定義的行為。
>> [學生]：哦，確實如此。好吧。
所以，當你想返回一個指針，這是在使用中的malloc來。
我其實只是返回的malloc（3 *表示sizeof（int））。
我們將在malloc的在第二，但對malloc的想法是所有的局部變量
始終走在堆棧中。
任何malloced的堆，它會永遠，始終是在堆上
直到你明確地釋放它。
因此，這意味著，當你的malloc東西，在函數返回後，它要生存下去。
[學生]程序停止運行後，它會生存嗎？ >>序號
好了，所以它會在那裡，直到該程序是所有的方式運行。 “是的。
我們可以去當程序停止運行時，會發生什麼。
您可能需要提醒我，但是這是一個完全獨立的東西。
[學生]的malloc創建一個指針？ >>呀。
的malloc的 - >> [學生]我認為的malloc指定的內存塊的指針可以使用。
[鮑登我想，圖。 >> [學生]因此，雖然此功能嗎？
[學生]是啊，malloc的指定，您可以使用一個內存塊，
然後返回該內存塊的地址。
>> 鮑登]是啊。所以，當你的malloc，你抓住一些的內存塊
這是目前在堆中。
如果堆太小，則堆只是要發展壯大，它生長在這個方向。
因此，讓我們說，堆太小。
然後，它的增長一點點，返回一個指向塊，只是增長。
當你免費的東西，你有更多的空間在堆中，
於是在以後調用malloc的，可以重複使用，您以前釋放的內存。
malloc和free重要的事情是，它可以完全控制
這些內存塊的整個生命週期。
全局變量是永遠活著。
在其範圍內的局部變量還活著。
只要你走過去花括號，局部變量都死了。
Malloced記憶是活著的時候，你希望它是活著的
然後被釋放，當你告訴它被釋放。
其實這些都是只有3種類型的內存，真的。
自動內存管理，這是堆棧。
事情發生自動為您。
當你說詮釋的x，分配的內存詮釋x。
當x超出範圍時，內存回收的x。
有動態內存管理，這是malloc的，
這是當你有控制。
您可以動態決定內存時應該和不應該被分配。
然後是靜態的，它只是意味著它永遠常存，
這是全局變量是什麼。
他們只是一直在內存中。
>> 有問題嗎？
[學生]：你可以定義一個塊用花括號
但不必有一個if語句或while語句或類似的東西嗎？
您可以在一個函數中定義一個塊，但有花括號。
[學生]：所以，你不能只是像一個隨機的一對花括號中的代碼
有局部變量嗎？ >>是的，你可以。
裡面的int酒吧，我們可以有{Y = 3;}。
這應該是在這裡。
但是，這完全定義的詮釋y的範圍。
之後，第二個大括號，Y不能使用了。
你幾乎從來沒有這樣做，雖然。
程序結束時會發生什麼，
有一個誤解/的一半謊言，我們只是使事情變得更容易給人以種。
我們告訴你，當你分配內存
你分配一些內存塊，該變量。
但是你沒有真正直接接觸RAM永遠在你的程序中。
如果你想起來了，我怎麼德魯 -
實際上，如果你通過在GDB中，你會看到同樣的事情。
不管有多少次你運行你的程序或你正在運行什麼程序，
棧總是要開始 -
你總是會看到的變數時，地址oxbffff的東西。
它通常是在該地區的某個地方。
但如何才能在2個節目可能有相同的內存的指針呢？
[學生]有一些任意指定的地方應該是在RAM oxbfff
其實是可以在不同的地方，當該功能被稱為。
是啊。這個詞是虛擬內存。
我們的想法是，每一個過程，每一個正在運行的程序在您的計算機上
有自己的 - 讓我們假設32位 - 完全獨立的地址空間。
這是一個地址空間。
它有自己完全獨立的4 GB的使用。
>> 所以，如果你同時運行2個節目，這個程序本身，看到4千兆字節
這個程序看到4 GB的本身，
這是不可能對這一計劃取消引用指針
從這項計劃中的內存。
虛擬內存是什麼是一個進程的地址空間的映射
實際的事情上RAM。
所以，就看您的操作系統知道，
嘿，這傢伙解引用指針oxbfff，這實際上意味著
他希望1000字節RAM，
而如果這個程序指針引用oxbfff，他真正想要的RAM字節10000。
他們可以隨意相距甚遠。
在一個單一的進程的地址空間，即使是真實的東西。
所以像看到所有4個千兆本身，但讓我們說 -
[學生]：是否每一個過程 -
比方說，你有一台電腦，只有4 GB的RAM。
每一個過程看到整個4 GB的嗎？ “是的。
但是，4千兆字節，它認為是騙人的。
這只是它認為這一切的記憶，因為它不知道任何其他過程中存​​在。
它只會使用盡可能多的內存，因為它實際上需要。
操作系統不會給RAM這一過程
如果它不使用任何內存在這整個地區。
它不會給該地區的記憶體。
但這樣的想法是 - 我想 - 我不能想到一個比喻。
類比是很難的。
的虛擬內存的問題之一，它解決的事情之一
是的進程應該是彼此完全不知道。
所以你可以寫任何程​​序，任何指針解除引用，
喜歡只寫一個程序，說*（ox1234），
而這解引用的內存地址為1234。
>> 但它的操作系統，然後翻譯一下1234手段。
所以，如果1234恰好是一個有效的內存地址，這個過程中，
就像是在堆棧上或什麼的，然後將返回值的內存地址
據的過程都知道。
但是，如果1234是不是一個有效的地址，如發生土地
在一些小的內存，這裡說的是超越的堆棧和堆超越
和你還沒有真正使用，那麼這時候你得到的東西一樣的segfaults
因為你接觸的記憶，你不應該接觸。
這也是如此 -
一個32位系統，32位意味著你有32位以確定一個內存地址。
這就是為什麼指針為8個字節，因為32位是8個字節 - 或4個字節。
指針是4個字節。
所以，當你看到一個指針一樣oxbfffff上，即是 -
在任何給定的程序中，你可以構建任意的指針，
任何地方，從OX0的牛8 f's的 - FFFFFFFF。
[學生]：你不是說他們是4個字節？ >>呀。
[學生]然後每個字節 - >> [鮑登]十六進制。
十六進制 - 5，6，7，8。所以指針，你要總是在十六進制。
這只是我們如何分類的指針。
每2個數字的十六進制數是1個字節。
因此，有4個字節是8個十六進制數字。
因此，每一個指針在32位系統將是4個字節，
這意味著，在你的過程，你可以構造任意4個字節
和一個指針，它
這意味著，只要它是知道的，它可以處理一個完整的2到32個字節的存儲器。
雖然它並沒有真正訪問，
即使你的電腦只有512兆，它認為它有那麼多的記憶。
和操作系統是足夠聰明的，它只會分配你真正需要的。
它不只是去了，哦，一個新的進程：4個音樂會。
>> 是啊。 >> [學生]什麼牛是什麼意思？你為什麼不寫呢？
這僅僅是十六進制的符號。
當你看到一個數字開始牛的，連續的東西是十六進制的。
[學生]您解釋有關程序結束時會發生什麼。 “是的。
程序結束時會發生什麼事是操作系統
只是，它已經為這些地址，這就是它的映射刪除。
操作系統可以現在只是給另一個程序使用該內存。
[學生]好的。
所以，當你分配在堆或堆棧或全局變量或任何東西，
他們都只是消失盡快程序結束
因為操作系統現在是免費的，任何其他進程的內存。
[學生]：即使有可能還是寫的值嗎？ >>呀。
值很可能仍然存在。
這只是這將是很難得到他們。
它更難以得到他們比是在一個已刪除的文件
因為被刪除的文件類型的坐在那裡，很長一段時間，和硬盤驅動器是大了很多。
因此，它要覆蓋的不同部分的內存
在它發生之前，該文件用於在覆蓋的內存塊。
但主記憶體，RAM，循環快了很多，
所以要非常迅速地被覆蓋。
或其他任何問題嗎？
[學生]我有一個不同的題目的問題。 “好了。
有沒有人有問題嗎？
>> 好吧。不同的主題。 >> [學生]好吧。
我所經歷的實踐考驗，
在其中的一個，它是談論的sizeof
和它返回的值或不同類型的變量。 “是的。
它說，int和long都返回4，所以他們都是4個字節長。
是一個int和long之間有什麼區別呢，還是同樣的事情嗎？
是的，是有差別的。
C標準 -
我可能會陷入困境。
就像C標準C是什麼，官方文件C.
這是它說什麼。
因此，在C標準只是說，一個字符將永遠，永遠是1字節。
之後的一切 - 簡短的永遠只是定義為大於或等於一個字符。
這可能是嚴格大於，但不積極。
一個int剛剛定義為大於或等於一個短。
長定義為大於或等於int。
和長的長是大於或等於長。
因此，C標準定義是唯一的相對順序的一切。
實際的內存佔用量普遍實施，
但它在這一點上相當不錯的。 >> [學生]好吧。
因此，短褲幾乎總是為2個字節。
詮釋幾乎總是要為4個字節。
長期多頭幾乎總是​​為8個字節。
和渴望，這取決於您使用的是32位或64位系統。
如此長的是將對應的系統的類型。
如果您使用的是32位系統，如家電，這將是4個字節。
如果您使用的是64位的，想了很多最新的計算機，這將是8個字節。
>> 整數是幾乎總是在這一點上的4個字節。
長期多頭幾乎都是8個字節。
在過去，整數用於僅是2個字節。
但是請注意，這完全滿足所有這些關係大於等於。
，只要是完全可以是相同的大小為一個整數，
它也可以是相同的大小作為一個長長。
它只是恰巧是在99.999％的系統，它是將等於
int或一個很長很長。它僅僅依賴於32位或64位。 >> [學生]好吧。
在彩車上，是如何指定的小數點位？
作為二進制一樣嗎？ >>呀。
你不需要知道，CS50。
你甚至不知道，在61。
你不好好學習，真的在任何課程。
這只是一個表象。
我忘了確切的位分配。
浮點的想法是，你分配一個特定的比特數來表示 -
基本上，一切都在科學記數法。
所以，你分配一個特定的數位代表的數量，如1.2345。
我不能代表一個數字位數多於5。
然後，你也分配一個特定的數位，它往往能像
你只能去到了一定的數量，那樣你可以有最大的指數，
和你只能去到一定指數，
喜歡，你可以有最小的指數。
>> 我不記得確切的方式位被分配到所有這些值，
但在一定的比特數的致力於為1.2345，
另一個一定的比特數，致力於指數，
它的唯一可能代表一個具有一定規模的指數。
[學生]和雙？那是像一個額外的長期持股量呢？ >>呀。
這是同樣的事情，但現在你用8個字節，而不是4個字節為float。
現在，您就可以使用9位或10位，
而這將是能上去到第300，而不是100。 >> [學生]好吧。
花車也是4個字節。 “是的。
好了，再次，它可能取決於整體上普遍實施，
但花車為4個字節，雙打有8個。
雙打被稱為雙，因為它們的兩倍大小的花車。
[學生]好的。以及是否有兩雙嗎？ >>有沒有。
我想 - >> [學生]喜歡長期多頭？ >>呀。我不認為如此。是。
[學生]在去年的測試的主要功能有問題
是程序的一部分。
答案是，它並沒有你的程序的一部分。
在什麼情況下？這是我所看到的。
[波頓似乎 - >> [學生]什麼情況？
你有問題嗎？ >> [學生]是的，我可以肯定拉起來。
它沒有，從技術上說，但基本上將是。
[學生]我看到了一個不同的年份的。
這是True或False：一個有效的 - “”哦，。c文件嗎？
[學生]所有的文件必須有 - [都講一次 - 不知所云]
好吧。所以這是分開的。
>> 。c文件只需要包含的功能。
你可以編譯成機器代碼，二進制文件，不管，
沒有它的可執行文件。
一個有效的可執行文件必須有一個main函數。
你可以寫100個函數在1個文件，但沒有主
，然後編譯為二進制，
那麼你就寫另一個文件，只有主，但這些函數調用了一堆
在這個二進制文件在這裡。
因此，如果你正在做的可執行文件，這就是鏈接器
是它結合了這2成一個可執行的二進制文件。
因此，一個c文件並不需要在所有的主要功能。
而在大的代碼庫，你會看到成千上萬的文件和1個主文件。
還有問題嗎？
[學生]是另一個問題。
它說是一個編譯器。 True或False？
得到的答案是假的，我明白了為什麼它不是像鏗鏘。
但我們所說的是什麼，如果不是嗎？
Make是基本上只是 - 我可以清楚地看到它調用它。
但它只是運行命令。
製作。
我可以拉起來。是啊。
哦，是的。同時也要做到這一點。
這說的make工具的目的是自動確定
一個大程序都需要重新編譯件
發出的命令重新編譯它們。
你可以讓文件，絕對是巨大的。
讓看文件的時間戳記，就像我們之前說的，
你可以編譯單個文件，並且它不是，直到你得到的鏈接器
他們拼湊成一個可執行文件。
所以，如果你有10個不同的文件，你犯了一個變化1，
那麼是什麼牌子要做的只是重新編譯，1個文件
然後重新鏈接起來。
但比它更笨。
它是由你來完全確定，這就是它應該做的。
默認情況下，有能力認識到這一點時間戳的東西，
但你可以寫一個make文件做任何事情。
你可以寫一個文件，這樣，當你鍵入它只是CD到另一個目錄。
我感到沮喪，因為我粘性裡面的一切，我的產品
然後我看到的PDF從Mac。
>> 所以我去搜索，我可以幹什麼去了，連接到服務器，
連接到服務器，我為我的設備，然後我打開PDF
被編譯使用LaTeX。
但我感到沮喪，因為每一次我需要更新的PDF，
我不得不將它複製到一個特定的目錄，它可以訪問
它越來越煩了。
所以我寫了一個make文件，你必須定義它使事情。
這是你如何使PDF LaTeX的。
就像任何其他的make文件 - 我猜你沒見過的牌子文件，
但我們有一個全球性的品牌在家電文件，該文件只是說，
如果你要編譯一個C文件，使用鏗鏘。
所以在這裡，我讓我說，在我的make文件
這個文件，你會想與PDF LaTeX的編譯。
所以它的PDF膠乳做編譯。
提出的，是不能編譯。它只是運行這些命令中指定的順序我。
所以它運行的PDF LaTeX的，它會將我希望它被複製到的目錄，
它的CD的目錄和做其他的事情，
但它是所有認識的文件改變時，
，如果它的變化，然後它會運行它應該運行的命令
當文件更改。 >> [學生]好吧。
我不知道在哪裡的全球MAKE文件是為我檢查出來的。
其他問題嗎？任何東西，從過去的測驗？任何指針的東西嗎？
有一些微妙的指針一樣的東西 -
我不會能夠找到一個競猜的問題上 -
但就像這樣的事情。
請確保你明白，當我說* X * Y -
這不正是任何東西，我猜。
但是，像* X * Y，那是2個變量是在棧上。
當我說X = malloc的（如sizeof（int）），X仍然是一個變量在棧上，
malloc的一些塊以上的堆，我們在x點的堆。
>> 因此，在棧上的堆的東西。
無論何時，只要你的malloc什麼，你不可避免地存儲它裡面一個指針。
因此，該指針是在棧上，malloced塊在堆中。
很多人感到困惑，並說* X = malloc的，x是在堆上。
號X點是在堆上。
x本身是在棧上，無論出於何種原因，除非你有X是一個全局變量，
在這種情況下，它正好是在另一個區域中的內存。
因此，跟踪，這些盒子和箭頭圖是很常見的測驗。
或者，如果它不是0測驗，測驗1。
你應該知道所有的這些，在編譯的步驟
因為你必須回答這些問題。是。
[學生]：我們能不能去這些步驟 - >>當然。
我們之前的步驟和編譯預處理，
編譯，彙編和鏈接。
預處理。那是幹什麼的？
這是最簡單的一步 - 嗯，不喜歡 -
這並不意味著它應該是顯而易見的，但是它是最容易的一步。
你們能實現它自己。是啊。
[學生]你有你的，包括像這樣的副本，然後還定義。
它看起來的東西如＃include和＃define，
它只是複製和粘貼那些真正的意思。
因此，當你說＃cs50.h的，預處理的複製和粘貼cs50.h
到該線。
當你說＃定義x為4，預處理整個程序
4 x的所有實例替換。
因此，預處理器需要一個有效的C文件，並輸出一個有效的C文件
事情已經複製和粘貼。
所以，現在編譯。那是幹什麼的？
[學生]從C到二進制。
>> 鮑登]不走，一路為二進制。
[學生]為機器代碼呢？ >>這是不是機器代碼。
[學生]大會？ >>大會。
在大會之前，去所有的方式為C代碼，
和大多數語言做這樣的事情。
選擇任何高級語言，如果你要編譯它，
它的編譯步驟。
首先，它要編譯Python到C，那麼它會編譯C大會，
然後，大會會得到轉換為二進制。
所以編譯是把它從C到大會。
這個詞編譯通常是指把它從一個更高的水平
到一個較低的電平的編程語言。
因此，這是唯一的編譯步驟，你開始與一個高層次的語言
並最終在一個低層次的語言，這就是為什麼被稱為編譯步驟。
[學生]在編寫過程中，讓我們說你已經完成了＃cs50.h.
編譯器重新編譯cs50.h，類似的功能，在那裡，
翻譯成彙編代碼為好，
或將它複製並粘貼大會前的東西嗎？
cs50.h將幾乎永遠不會結束在大會。
函數原型和事情的東西一樣，只是你要小心。
它保證了編譯器可以檢查的事情，比如你調用函數
用正確的返回類型和正確的參數之類的東西。
>> 所以cs50.h將預處理到文​​件中，然後當它的編譯
它基本上是扔掉後，確保一切都被正確調用。
但定義的函數在CS50庫，這是分開cs50.h，
那些不會被單獨編譯。
這實際上會在連接步驟，所以我們會在第二。
但首先，什麼是裝配？
[學生]：大會為二進制？ >>呀。
組裝。
我們不把它編譯，因為大會是一個很值得純二進制翻譯。
大會二進制的邏輯是非常小的。
這就像在一個表中查找，哦，我們有這個指令;
對應於二進制01110。
因此，組裝一般輸出。o文件的文件。
o文件是我們之前說的，
怎樣文件不需要有一個主要的功能。
可將任何文件編譯成。o文件，只要它是一個有效的C文件。
它可以被編譯成。Ø。
現在，連接實際上是帶來了一堆的。o文件，並給他們帶來一個可執行的。
因此，聯做的是你能想到的的CS50庫的。o文件。
這是一個已編譯的二進制文件。
因此，當你編譯你的文件，你的hello.c的，這調用getString，
，hello.c中被編譯成hello.o
hello.o是二進制。
它使用GetString的，所以它需要去到cs50.o的，
連接器smooshes在一起，並將其複製到這個文件中的GetString
和出來一個可執行文件，它需要的所有功能。
因此，cs50.o是不實際的O文件，但它是足夠接近，有沒有根本的區別。
因此，聯剛帶來了一大堆的文件
分別包含了所有的功能，我需要使用
並創建將實際運行的可執行文件。
>> 因此，這也是我們之前說什麼
在那裡你可以有1000個。c文件，在編譯所有。o文件，
這可能會需要一段時間，那麼你改變1。c文件。
你只需要重新編譯。c文件，然後重新鏈接一切，
連接一切重新走到一起。
[學生]當我們連接我們寫lcs50嗎？
是啊，所以lcs50。這標誌信號連接器，你應該鏈接該庫中。
有問題嗎？
我們走了過來二進制以外的第一堂課，5秒嗎？
我不認為如此。
你應該知道，我們已經討論了所有的大的OS，
，你應該是可以的，如果我給你一個函數，
你可以說這是大O，大約。好，大O是粗糙的。
所以如果你看到嵌套的for循環遍歷相同數量的東西，
如INT I，I <N，J，J > [學生] n的平方。 >>它往往為n的平方。
如果您有三重嵌套的，它往往是n的三次方。
這樣的事情，你應該能夠立即指出。
你需要知道插入排序，冒泡排序和歸併排序和所有的人。
這是容易理解為什麼他們是那些N的平方和n日誌n和所有的
因為我覺得有一個測驗的一年，我們基本上給你
冒泡排序算法的實現和說，“什麼是這個函數的運行時間？”
所以，如果你認出來冒泡排序，那麼你可以立即回答n的平方。
但是，如果你只是來看看，你不甚至需要認識到它的冒泡排序;
你可以說這是這樣做的，這。這是n的平方。
[學生]有任何強硬的例子，你可以拿出，
像類似的想法搞清楚？
>> 我不認為我們會給你任何強硬的例子。
冒泡排序的是艱難的，因為我們會去，
甚至認為，只要你明白，你遍歷數組
為每個數組中的元素，這將是東西的N平方。
有一般的問題，比如在這裡，我們有 - 哦。
就在幾天前，道格聲稱，“我已經發明了一種算法，可以排序的數組
“n個數O（log n）的時間！”
那麼，我們如何知道這是不可能的嗎？
[聽不見的學生反應] >>呀。
最起碼，你要摸每個數組中的元素，
所以這是不可能的，對數組進行排序 -
如果一切是在未排序的順序，那麼你將要接觸的數組中的一切，
所以這是不可能做到這一點比O的n。
[學生]您向我們展示了這個例子能夠做到這一點，在O n個
如果你使用了大量的內存。 >>呀。
而that's - 我忘了什麼that's - 計數排序？
嗯。這是一個整數的排序算法。
我一直在尋找這個特殊的名字，我不記得上週。
是啊。這些類型的排序，可以完成的事情，大O的n。
但也有局限性，你只能使用整數到了一定的數量。
另外，如果你想的東西that's排序 -
如果您的陣列為012，-12，151，400萬，
然後，單元素要完全毀掉整個分揀。
>> 有問題嗎？
[學生]如果你有一個遞歸函數，它只是使遞歸調用
在一個return語句，這是尾遞歸，
這不使用更多的內存在運行時
或至少​​使用可比較的記憶體作為一個迭代的解決方案嗎？
波頓：是的。
它可能會有點慢，但不是真的。
尾遞歸是相當不錯的。
再看看堆棧幀，讓我們說，我們有主
我們有int酒吧（X）的東西。
這不是一個完美的遞歸函數，但回報酒吧（X - 1）。
所以，很顯然，這是有缺陷的。您需要基礎案例之類的東西。
但這裡的想法是，這是尾遞歸，
這意味著，當主調用酒吧，它會得到它的堆棧幀。
在這個堆棧幀，將是一個小的內存塊
對應其參數x。
因此，讓我們說主要發生在調用酒吧（100）;
因此，x是要開始為100。
如果編譯器認識到這是一個尾遞歸函數，
然後在酒吧禁止遞歸調用，
而不是製造新的棧幀，這是堆棧中開始增長在很大程度上，
最終它會運行到堆，然後你得到的segfaults
因為內存開始碰撞。
>> 因此，而不是它自己的堆棧幀，它可以實現，
哎，我從來沒有真正回來到這個堆棧幀，
所以不是我就替換此參數與99，然後開始酒吧。
，然後它會再次將達到迴轉桿（X - 1），
，而不是一個新的堆棧幀，將剛剛替換其當前參數98
然後跳回到最開始的吧。
這些操作，更換，堆棧上的值，跳回到開始，
是非常有效的。
所以這不僅是一個單獨的函數相同的內存使用情況，這是迭代
因為你只能使用1堆棧幀，但你沒有苦難的缺點
調用函數。
調用函數可能會有點昂貴，因為它需要做的這一切設置
和拆卸，這一切的東西。
因此，這尾遞歸還是不錯的。
[學生]：為什麼不創建新的步驟？
因為它意識到它並不需要。
調用酒吧剛剛返回的遞歸調用。
因此，它並不需要做任何的返回值。
它只是將立即返回。
因此，它只是要更換自己的參數，並重新開始。
還有，如果你沒有尾遞歸版本，
然後你會得到所有這些酒吧，這個酒吧返回
它有這一個，然後返回它的值，酒吧立即返回
，並返回它的值這一個，那麼它只是將立即返回
這一個，並返回它的值。
因此，要保存彈出所有這些東西的堆棧
因為返回值僅僅是將要通過所有的方式回到反正。
那麼為什麼不直接取代我們的觀點與更新的參數，並重新開始嗎？
如果該函數不是尾遞歸，如果你做這樣的事情 -
[學生]如果酒吧（X + 1）。 >>呀。
>> 所以，如果你把它的條件，那麼你正在做的事情的返回值。
或者即使你只是做回2條（X - 1）。
所以，現在巴（ - 1）需要返回，以便它來計算該值的2倍，
所以現在它需要有自己的獨立的堆棧幀，
現在，無論你怎麼努力，你將需要 -
這是不是尾遞歸的。
[學生]我會盡量把一個遞歸的目標是一個尾遞歸 -
鮑登在一個理想的世界，但在CS50你沒有。
一般情況下，為了得到尾遞歸，成立一個額外的參數
欄將採取整數X到Y
y對應到極致的事情，你要返回。
那麼你將要返回酒吧（X - 1），2 * Y。
所以，這只是一個高層次的，你怎麼變換的事情是尾遞歸。
但是，額外的參數 -
然後在結束時你達到你的基本情況，你剛剛返回y
因為你已經積累的全部時間，你想要的返回值。
你這種已經這樣做迭代，但使用遞歸調用。
有問題嗎？
[學生]也許指針的算術運算，如在使用字符串。 “當然可以。
指針的算術運算。
使用字符串時，很容易因為字符串是char明星，
字符是永遠的，始終是一個單字節，
指針的算術運算相當於定期算術當你在處理字符串。
遠的不說的char * s =“你好”。
因此，我們有一個內存塊中。
它需要6個字節，因為你總是需要空終止符。
和char * s將要指向這個數組的開始。
因此，S點。
現在，這基本上是任何數組是如何工作的，
無論它是否是一個由malloc或無論是在堆棧上的回報。
任何數組基本上是一個指針陣列的開始，
那麼任何數組操作，任何索引，只是進入該數組一定的偏移。
>> 所以當我說類似[3]這是怎麼回事s和計數3個字符中。
因此s [3]，我們有0，1，2，3，因此s [3]將參考本升。
[學生]我們可以達到相同的值，執行s + 3，然後括號明星的嗎？
是。
這是相當於*（+ 3）;
，這是永遠總是相等的，無論你做什麼。
你永遠需要使用括號的語法。
您可以隨時使用*（+ 3）語法。
人們往往喜歡括號語法。
[學生]因此，所有的數組實際上是指針。
有輕微的區別，當我說×[4] >> [學生]這是否創建內存嗎？
鮑登，是要創建4個的整數堆棧上的，所以16個字節的整體。
它會在棧上創建16個字節。
x未存儲在任何位置。
這僅僅是一個符號參照開始的事情。
因為你聲明的數組裡面的這個函數，
編譯器會做的僅僅是變量x的所有實例都替換
與它發生在選擇把16個字節。
它不能這樣做，因為用char * s是一個實際的指針。
它是免費的，再點其他的事情。
x是一個常數。你不能擁有它指向不同的數組。 >> [學生]好吧。
但這樣的想法，這個索引是一樣的，不管它是否是一個傳統的陣列
或者如果它是一個指針的東西，或者如果它是一個到malloced數組的指針。
而事實上，它是相等的，這是同樣的事情。
它實際上只是翻譯的括號裡面是什麼，什麼是左括號內，
把它們加在一起，並取消引用。
因此，這是一樣有效（+）或S [3]。
[學生]你能有2維數組的指針指向？
>> 它的難度。傳統上，沒有。
一個二維數組是一維數組使用一些方便的語法
因為當我說詮釋x [3] [3]，這真的只是1陣列的9個值。
因此，當I指數，編譯器知道我的意思。
如果我說，X [1] [2]，它知道我要到第二行，所以​​將跳過第3，
那麼想的第二件事，所以它會得到這一個。
但它仍然只是一個一維數組。
所以，如果我想指定一個指向該數組的指針，
我想說的* p = X;
x的類型是 -
粗略的說這是x的類型，因為它只是一個符號，它不是一個實際的變量，
但它僅僅是一個int *。
x是剛剛開始的指針。 >> [學生]好吧。
因此，我將無法訪問[1] [2]。
我認為是有特殊的語法來聲明一個指針，
什麼可笑的，如int（* p [ - 這是絕對荒謬的。我什至不知道。
但有語法聲明函數指針像括號和活動。
它甚至有可能不會讓你這樣做。
我回頭看的​​東西，將真相告訴我。
我會尋找它以後，如果有一個語法點。但你永遠不會看到它。
即使語法是過時的，如果你使用它，人們會感到困惑。
多維數組是非常罕見的，因為它是。
你幾乎 -
好吧，如果你在做矩陣的事情，它不會是罕見的，
但在C中，你很少會被使用多維數組。
是啊。 >> [學生]：比方說，你有一個很長的陣列。
>> 因此，在虛擬內存中，它似乎是所有連續，
彼此旁邊的類似的元素，
但在物理內存中，它有可能為被分裂了嗎？ “是的。
虛擬內存的工作原理是，它只是分離 -
的分配單元是頁面，​​這往往是4千字節，
所以說，當一個進程，哎，我想使用此內存，
操作系統會分配它的那個小4千字節的內存塊。
即使你只使用一個單字節的內存塊在整個不大，
操作系統是要給它完整的4千字節。
因此，這是什麼意思是，我可以 - 讓我們說這是我的籌碼。
該協議棧可以被分開。我的堆棧可能是兆字節，兆字節。
我的籌碼將是巨大的。
但棧本身被分裂成單獨的頁面，
如果我們看一下在這裡，讓我們說，這是我們的RAM，
如果我有2 GB的RAM，這是我的第零個字節的RAM地址為0，如實際，
這是2 GB一路下跌。
因此，該頁面可能對應到這個塊在這裡。
在這裡，該頁面可能與此塊。
這可能對應於這一個在這裡。
因此，操作系統是免費分配物理內存
任何單獨的頁面隨意。
這意味著，如果這條邊界發生跨越陣列，
發生一個數組左和右以此順序一個頁面
那麼該數組將被分割在物理內存中。
然後當你退出程序，當進程結束時，
這些映射將被刪除，然後它是免費的，使用這些小的塊，其他的事情。
還有問題嗎？
[學生]指針的算術運算。 >>哦，是的。
字符串比較容易，但看著像int類型，
使之恢復為int x [4];
這是否是一個數組無論是到malloced 4個整數的數組指針，
它會以同樣的方式來對待。
[學生]因此，數組的堆？
[鮑登]數組是不是在堆上。 >> [學生]哦。
>> [鮑登]這類型的磁盤陣列的傾向是在堆棧上
除非你宣布它在， - 忽略全局變量。不要使用全局變量。
裡面的功能，我說×[4];
這將在棧上創建一個整數4塊，這個數組。
但是這個malloc（4 *表示sizeof（int））;要去的堆。
但在這一點上我可以在幾乎相同的方式，使用x和p
其他比我說的例外，前行約，您可以重新分配p。
從技術上講，它們的尺寸有所不同，但是這是完全不相干的。
你從來沒有真正使用它們的大小。
我可以說的p P [3] = 2;或×[3] = 2;
您可以使用完全相同的方式。
因此，指針的算術運算 - 是的。
[學生]你沒有做P *如果你有括號？
括號內是一個隱式的間接引用。 “好了。
其實，你在說什麼的你可以得到多維數組
的指針，你可以做的是一樣的東西，比方說，** PP = malloc的（如sizeof（*）* 5）;
我就寫了這一切第一。
我不想要的那一個。
好吧。
我在這裡做的是 - 這應該是PP [I]。
因此，PP是一種指向指針的指針。
您正在mallocing的PP指向的陣列5整數星。
因此，在內存中，你必須在棧上頁
要5塊，這些都是自己的指針指向一個數組。
然後，當我的malloc在這裡，我的malloc的那些個人，每個指針
應該指向一個單獨的4個字節的堆塊。
因此，這點到4個字節。
而這一次不同的4個字節。
>> 所有的人都指向自己的4個字節。
這給了我做多維的事情的一種方式。
我能說的PP [3] [4]，但現在這是不一樣的東西，多維數組
因為多維數組它翻譯[3] [4]到一個單一的偏移量x數組。
這解引用，P，訪問的第三個指標，然後解引用
訪問 - 將是無效的 - 第二個索引。
而當我們的int x [3] [4]前一個多維數組
和雙支架時，它真的只有一個解引用，
你一個單一的指針和一個偏移量，
這是真正的2D引用。
你跟著2個獨立的指針。
因此，這在技術上也是可以讓你有多維數組
其中每個單獨的陣列是不同的尺寸。
因此，我認為鋸齒狀的多維數組是它叫什麼
因為真正的第一件事可能指向的東西，有10個元素，
第二件事情可能指向的東西，有100個元素。
[學生]：是否有任何限制數的指針，你可以有
指向其他指針？ >>序號
您可以有int ***** p。
返回指針的算術運算 - >> [學生]哦。 >>呀。
[學生]如果我有int ** p，然後我做了一個間接引用和我說，P *是等於這個值，
它只會做1級提領嗎？ “是的。
所以，如果我要訪問的最後一個指針指向的東西 -
然後，你*** P。 “好了。
因此，這是p點到1塊到另一個塊，點，點到另一個塊。
然後，如果你做* P =別的東西，那麼你正在改變這
到現在指向一個不同的塊。 “好了。
>> [鮑登]，如果這些malloced，那麼你現在已經洩漏的內存
除非你碰巧有這些不同的參考
因為你不能得到那些的，你只是扔掉了。
指針的算術運算。
×[4];要分配4個整數的數組
其中x是要指向的數組的開始。
所以，當我說的東西，比如x [1]，我想它的意思去的第二個整數的數組，
這將是這一個。
但實際上，這是4個字節到數組中，因為這個整數佔用4個字節。
因此，偏移量為1的真正含義偏移量為1
倍的大小的任何類型的數組。
這是一個整數數組，所以它知道做1次為int的大小，當它想抵消。
其他的語法。請記住，這是相當於*（X + 1）;
當我說指針+ 1，返回的地址指針存儲
加1倍的大小的指針的類型。
因此，如果x = ox100，那麼x + 1 = ox104。
你可以濫用這一點，說什麼像char * C =（CHAR *）X;
現在c將是相同的地址作為x。
c是將是等於ox100，
但C + 1將是等於ox101的
因為指針的算術運算取決於您要添加的類型的指針。
所以C + 1，它著眼於C，它是一個字符指針，所以它要增加1倍大小的char，
總是為1，所以你得到101，
而如果我這樣做，X + 1 x，它也仍然是100將是104。
[學生]：你可以使用C + +，以推進指針加1呢？
是的，你可以。
你不能這樣做，因為x與x只是一個符號，它是一個常量，你不能改變x。
>> 但C恰好是一個指針，所以C + +是完全有效的，這將增加1。
如果c是一個int *，然後是C + + 104。
+ +指針的算術運算正如C +會做指針算術。
其實，這是怎麼了很多事情，比如合併排序 -
創建副本的事情，而不是相反，你可以通過 -
就像如果我想通過這半年的數組 - 讓我們清除一些。
比方說，我想通過這一邊的數組的功能。
，我會通過該功能是什麼？
如果我通過X，我通過這個地址。
不過，我想通過這個特定的地址。所以，我應該通過什麼嗎？
[學生]指針+ 2？
[鮑登]所以x + 2。是。
這將是這個地址。
您還可以經常看到它為x [2]，然後在該地址。
所以，你需要採取的地址，因為它的支架是一個隱式的間接引用。
X [2]指的是在此框中的值，然後你要的那個盒子的地址，
所以你說＆X [2]。
所以，如何在合併排序的東西，你想通過一半的東西的清單
你真的只是通過X [2]，而現在的遞歸調用，
從那裡開始我的新數組。
最後一分鐘的問題。
[學生]如果我們不把一個符號或一個 - 那是什麼叫什麼名字？ >>明星嗎？
[學生]星。 “從技術上講，反引用運算符，但 - >> [學生]：取消引用。
>> 如果我們不把一個明星或一個符號，會發生什麼，如果我只是說y = x和x是一個指針？
y的類型是什麼？ >> [學生]我只想說，它的指針。
所以，如果你只是說y = x的，現在的X和Y點了同樣的事情。 >> [學生]點了同樣的事情。
如果X是一個int的指針嗎？ >>，它會抱怨，因為你不能分配的指針。
[學生]好的。
請記住，指針，即使我們把它們畫為箭頭，
真的，他們店 - * X - 實際上所有的x存儲類似ox100，
我們正好代表指向存儲在100塊。
所以當我說詮釋* Y = X，我只是複製ox100到Y，
我們只是要表示為y，也指向ox100。
如果我說我=（int）的X，然後我將存儲任何的價值ox100是
在它裡面，但現在它會被解釋為一個整數，而不是一個指針。
但是，你需要的演員，否則，它會抱怨。
[學生]：所以你的意思是投 -
它是將要鑄造的y值的x或鑄造詮釋的？
[鮑登什麼？
[學生]好的。在這些括號將是一個x或AY？
>> 鮑登]。 x和y是等效的。 >> [學生]好吧。
因為他們是兩個指針。 >>呀。
[學生]因此，它會存儲100的十六進制整數形式呢？ >> [鮑登]是啊。
但不是無論它指向的值。
鮑登]是啊。 >> [學生]因此，只要整數形式的地址。好吧。
[鮑登]如果你想一些奇怪的原因，
你可以只處理指針和不會處理整數
只是，如int * x = 0處。
然後，你會得到真正的困惑，指針的算術運算後開始發生。
因此，它們存儲的數字是毫無意義的。
它只是你怎麼收場解釋它們。
所以我複製ox100從int *為int，
我是自由分配 - 你們可能會被罵不投 -
我可以自由分配（*）ox1234到這個任意整數*類似。
所以ox123是一樣有效的內存地址＆Y。
＆Y發生，這幾乎是ox123返回的東西。
[學生]：這是一個非常酷的方式，從十六進制到十進制的形式，
一樣，如果你​​有一個指針，將其轉換成一個int類型的嗎？
鮑登]你真的可以使用類似printf打印。
比方說，我有int y = 100。
因此我們知道printf（“％d個\ n - 你應該已經知道 - 打印為一個整數，％X。
我們只需要打印十六進制的。
因此，一個指針存儲為十六進制，
和沒有存儲為十進制，整數。
一切都以二進制形式存儲。
只是我們往往顯示為十六進制的指針
因為我們認為在這4個字節的塊的東西，
和內存地址往往是熟悉的。
我們是一樣的，如果它開始與BF，那麼它正好是在棧上。
因此，這只是我們的解釋為十六進制的指針。
好吧。最後還有什麼問題嗎？
>> 我會在這裡了一下後，如果你還有什麼。
這是該結束。
>> [學生]耶！ [掌聲]
>> [CS50.TV]