[Powered by Google Translate] [第4週,續] [戴維·J·馬蘭 - 哈佛大學] [這是CS50。 - CS50.TV] 這是CS50,這是結束4週。 因此,一些好消息和一些壞消息。 星期一不上課,沒有問題設置下週,。 [學生歡呼] 你不會喜歡,這是怎麼回事。 但是,我們確實有這個,而不是下週三, 也按照教學大綱週五演講下週五,這樣我們就可以留在賽道上。 但是,一切都將被拍攝下來,像往常一樣,所以不用擔心。 而對於測驗0朝週的結束,我們會做什麼 發布課程的網頁cs50.net解釋 你應該有什麼樣的期望時,它的第一次測驗。 在一般情況下,這將是多項選擇題,是非,簡答題,短的編碼問題。 你不會被預計實現相當於 的問題上,你會看到一個pset中,你有一台電腦 和調試器之類的,但會有小的編碼問題。 的確,最好的指導,得到感CS50測驗是像 就是到cs50.net去,去測驗鏈接, 你可以看到價值在過去幾年的測驗。 只是實現課程並不總是相同多年來。 有時候,我們增加,有時相減, 所以如果你看到一些話題之一,那些古老的測驗 你不知道它在說什麼,這是,我們沒有覆蓋 或者,我們並沒有覆蓋它。 但是,評論的形式,這個星期天,星期一和星期二 以及在週日晚上的課程廣泛的審查會議 - 課程的網頁上公佈的時間和地點 - 你有機會檢討課程的教學研究員 今年,無論是在材料部分,作為一個完整的類, 和那些將被拍攝下來,像往常一樣。 好的。因此,事不宜遲,評論通過/失敗,並添加/刪除。 您可能已經看到我的筆記昨晚,這真的只是一些額外的放心 如果你是在那些特別不舒服的,或介於兩者之間 和你的感覺只是一點點在你的頭上, 實現這確實是很正常的,並有充足的支撐結構, 其中之一辦公時間為每提高我的電子郵件昨晚的意圖, 實現過類似的選項通過/失敗的一類這樣的 真的是作為一種機制,採取邊關閉的這樣一個過程, 因此,再次,如果你花這10個,15個,20個小時 只是想獲得一些pset的工作,你知道你的方式有90%-95% 但你不能找到一些該死錯誤,在一通/失敗的排序模型,沒關係。 我們的想法是,該機制可以去專注於其他pset 或睡眠,不管它是什麼,你要專注於。 所以知道你有,直到下星期二 - 技術上,5日(星期一), 但它是一個節日,所以這下星期二 - 切換合格/不合格分級或反之亦然。 而且,如果你真的在絕壁上,並考慮丟棄完全, 請抓住我講課後,我。 我們很樂意向你告別之前,至少聊天。 好的。因此,我們開始考慮關閉最後一次訓練車輪。 特別是,我們專注於字符串。 String是宣布的CS50庫中的東西的, 特別是在該稱為cs50.h的文件,我們將在本週和下週開始尋找。 但是,字符串是真的只是一個簡化的東西 這是一個有點更arcanely為char *。 CHAR我們熟悉的。這只是一個單一的字符。 *截至週一表示什麼? >> [學生]的指針。 一個指針。什麼是指針嗎? >> [學生]的地址。 這就像一個地址,一個在內存中的位置。 什麼是地址或位置,或記憶體? 同樣,我們所有的人都有筆記本電腦的演出或2 GB的RAM,最有可能的,這些天, 這意味著你有一個億或2億字節值得的內存。 它並不真正的問題是什麼身體看起來像, 但要信你可以列出所有的單個字節,自己的筆記本電腦 - 這是0字節,這是第1個字節,這是第2個字節億 - 而這正是一台電腦做什麼。 例如,當您分配的單個字符的空間, 在您的計算機的內存中顯然有地方住, 也許是在字節數12345, 這就是這裡的某個地方在您的計算機的內存中。 該字符的地址,然後是12345。 現在,在0週,通過現在到目前為止,我們還沒有真正關心 在那裡存儲在內存中的東西,因為我們通常使用的符號, 變量和數組其實在我們的數據。 但是,星期一,今天,你將有 更表達能力編寫程序 要真正操縱一台計算機的內存,您認為合適的, 既有良好的目的和壞的, 錯誤在學習這東西在這一點上是一種很常見的結果。 但什麼是它真正的意思,是一個char *? 讓繼續回到 - 和所承諾的今天,我們會回來Binky。 讓我們到這裡一個簡單的例子。 讓我保存這個文件為compare.c,讓我在這裡得到一些模板代碼 所以包括stdio.h中,讓我也給自己包括cs50.h.我會在有放大。 讓我開始寫主要的詮釋,主要(無效),現在我想要做這樣的事情: printf(“請給我一個字符串:”),然後我會使用字符串s中得到的getString 從用戶得到一個字符串,那麼我要問另一個用戶。 (“給我另一個字符串:”)和我通過GetString來,我要問他們。 我會打電話給它噸,因為T後,S和S為一個字符串,如果是一個好聽的名字,這是非常普通的。 GetString的,現在我只想要做完整性檢查,我要去說 (== T),然後我只是要告訴用戶輸出(“你輸入同樣的事情!\ n”); 否則,我要打印出來的東西(如“您所鍵入的不同的東西!\ n”) 或其他的句子。因此,類似的東西。 然後,像往常一樣,我會回來0這標誌著沒有什麼糟糕的事情發生, 我要繼續前進,編譯並運行這個程序。 但在週一,我們運行這個程序, 實際上是說,HELLO你好和再見不再見。 的行為,我們看到的是一個有點像。 讓我進入我的源目錄,在這裡變焦,並讓我們做作出比較。 編譯沒問題。讓我跑了比較。給我一個字符串:HELLO。 給我另一個字符串:HELLO。 您輸入不同的東西! 好了,讓我試試簡單的像50,50。您輸入不同的東西! 嗨,嗨。所以很明顯,這是怎麼回事。 但究竟是什麼理由來解釋為什麼? 顯然,12號線是完全不正常的。 這裡的根本問題是什麼?是啊。 >> [學生]的地址進行比較。 是的,沒錯。它實際上是比較地址 HELLO和HELLO存儲。 這不是比較的字母HELLO一遍又一遍, 因為什麼是真正發生的事情,這段時間我們一直在使用GetString - 黑板又是我們電腦的內存, 讓我們說我調用GetString後聲明一個變量s。 我的記憶是什麼樣子呢? 讓我們武斷地說,,長相像這樣。這是一個正方形。 和幾乎所有的時間在屏幕上,我畫的一塊內存 如果是32位我已經畫廣場這樣的,因為確實在家電, 一個指針,一個地址,為32位。這是一個int一樣。 這可以根據計算機系統的不同而有所差異。 你們誰是與你的Mac或PC是64位的事實,依稀熟悉, 實際上代表您的電腦使用的是64位指針, 64位地址,並躋身有利的一面,那是你的電腦 可以有更多的RAM比昔日。 長話短說,早在一天當計算機只使用32位 表示地址的最大字節數,你可以代表 在這種情況下,如果你有32位嗎? 所以4億美元,正確的,因為2到32是4億美元。 這個數字已再次發生的過程。 所以,如果你只有32位,你可以數到的最高數量是大約4億美元。 但是,這是一個基本的限制,直到幾年前的電腦 因為如果你只能算作高為4億美元, 不要緊,如果你買了8 GB的RAM,甚至5千兆字節的RAM; 你不能指望高,所以它是無用的。 您只能訪問您的計算機的內存中的第3或4 GB的。 這不再是一個問題了,你可以買的MacBook Pros筆記本電腦和戴爾 8 GB的RAM,甚至更多,這些天。 但是,如果我分配在這個程序很簡單指針,指針, 它可能看起來像在屏幕上,因為我們確實需要剝開這層。 我一直在說的字符串,但截至週一,字符串是真正的char *, 一些性格的地址。 因此,讓我們的訓練輪中斷,即使現在我們將繼續使用GetString。 所以,我宣布,這是一個內存塊,32位。 在這裡,默認情況下,在內存中嗎? >> [聽不見的學生反應] 那是什麼? >> [學生]垃圾。 >>垃圾。沒錯。 如果你的程序員不把一個變量的值,誰知道它是什麼呢? 有時你會得到幸運的,它是0,這是怎麼樣的一個不錯的,乾淨的默認值, 但正如我們所看到週一,有時完全是一派胡言, 一些非常大的正數或負數,從哪兒來? 是啊。 >> [學生]的功能。 >>呀。 通常情況下,被調用的函數,因為以前記得, 當你調用函數在內存中,他們採取了越來越多的空間從下往上, 盡快函數返回時,那段記憶得到重用 ,被稱為未來的傢伙,誰在使用相同的內存片。 如果你已經離開垃圾在那裡,以前的值, 我們可能會誤以為S作為有一定的價值時,我們真的不把任何東西存在。 因此,我們在這一點上看起來是這樣的RAM。 現在在右手邊的第7行,我們調用GetString時, 我們現在做了幾個星期,但真的這樣做是GetString的嗎? GetString的是一個有點聰明的的CS50人員的書面 ,只要用戶開始輸入密鑰,點擊輸入, GetString的數字用戶按下了多少按鍵, 我需要多少個字符分配RAM。 ,RAM,誰知道? 這是在您的計算機上的2千兆字節的內存或諸如此類的東西的地方。 但是,讓我們假設計算機空間的單詞HELLO。 我輸入的字是H-E-L-L-O。 如果我們得出這樣的字符序列,我們可以繪製它是這樣的。 不過,我需要做額外的事情。結束時的任何字符串在C屬於什麼? 空字符,這是我們寫的\ 0。 這是技術上的數字0,,但反斜線使更清晰 這是字面上的編號為0,整數0; 它不是,例如,報價引文結束,你可能會在鍵盤上鍵入0。 因此,這是HELLO。 了什麼,我們在週一,類似的函數的GetString 實際上返回所有這幾個星期呢? 這不是返回一個字符串,因為這本身並沒有真正的意思 因為字符串不存在。他們的一個製造的CS50庫的排序。 什麼是真正的字符串,技術上呢? >> [學生]這是第一個字符。 沒錯。這是很簡單的第一個字符的地址,用戶輸入的字詞。 所以,如果我的話HELLO結束的時候,人們的字節數123,然後在字節數124, 125,126,等等,如果我只是我從0字節數就到了, 真正的GetString返回簡直是數字123。 那麼,什麼被在s號為123,而不是字母H,而不是這個詞HELLO, 很簡單的地址,我能找到的第一個字母HELLO。 但是,這似乎並不像足了。我問你一個字符串,而不是一個字符。 那麼,如何才能或計算機知道ELLO種以及H? 我們有什麼樣的協議?是啊。 [學生]不斷告訴自己找到一些更多的字符。 “沒錯。 這種人機慣例,即當你處理字符串, 否則現在已知為char明星,你只需要找出 在生活中的每一個字符串的結束是真的只是一個for循環迭代, 一個while循環,什麼的,所以,當你找到的字符串的結尾 哦,現在你可以推斷出,整個單詞HELLO。 那些你知道在Java編程經驗 你可以調用。長和在其他語言中,你可以調用長度或類似的。 這是因為,在很多語言中,特別是被稱為面向對象的語言, 長的東西是種的一塊封裝在數據本身, 就像我們封裝的ID和姓名,房屋內的學生週一。 但是,C是低得多的水平。有沒有對象或類的,如果你聽說過這些術語。 你真的是內存地址。 因此,這是一種老式的方法較有趣的數據結構。 你有一個開始的第一個字符的地址值,如 ,然後就一些任意的約定,每個人都同意遵守。 因此,如何實現字符串的長度,我們提出了嗎? STRLEN,STRLEN,你們中的一些現在已經用了幾次。這是很簡單的,對不對? 這就像兩行代碼。 這幾乎是一個某種形式的for循環,也許有一個額外的局部變量。 但strlen的只是一個指針,然後開始尋找\ 0。 而一旦它發現它,它可以返回總數的步驟,它採取了在該字符串中。 因此,我們可以推斷,這是下一個。 假設,然後在第10行,因為我已​​經做了,我宣布噸。 這是一些垃圾的價值。在第一誰知道? 但在我右手邊的10調用的getString再次。 誰知道在哪裡結束了嗎? 讓我們武斷地說,操作系統搜房的方式在這裡。 我正好不約而同地再次鍵入H-E-L-L-O, 因此,我們可以得出相同類型的圖像。 但事實上,我已經重新繪製這幅畫是故意的 因為這是一個不同的HELLO超過這一點。 因此,這裡,這可能會對位置456,這是457,等等。 那麼,什麼被放在其中的問號? 在這種情況下,456。 我們選擇這些數字隨意,因為今天真 我們不會那麼在乎任何事物的地址是什麼。 我們所關心的是,我們可以計算出地址的某些數據,如HELLO。 所以,真的是大多數人都在談論的內存地址時,計算機科學 和談論的指針具體而言, 而不是費心找出123 - 誰在乎這個東西實際上是, 我們只知道它是在一些數字地址 - 我們簡化了世界,只是說S是指向該字符 ,t為指向這個角色。 而事實上,它是一個箭頭是很有意 因為從字面上現在s是指向在H和t指向其他的H 因為在一天結束時,它並沒有關係的地址是什麼, 但它的問題,我們有一些代碼的表達能力,地址。 我們還沒有真正操縱這些地址,只是還沒有 所以我們會看到,在這裡我們可以沒錯,排序做的事情與指針, 但現在在第12行從字面上我​​們比較的是什麼值 根據這個故事在第12行嗎? 我們說的是123,等於等於456?這絕對不是這樣的。 甚至在概念上,這個指針肯定是不一樣的,因為這 因為你叫GetString的兩倍,和GetString不會嘗試是超級聰明, 它不會嘗試來實現的,哦,你鍵入HELLO 5分鐘前; 讓我給你的,因為我以前給你相同的指針, 它只是分配一個新的內存塊,每次調用它。 那麼,我們如何解決這個問題? 如果需要更高的水平,我想比較字符串HELLO HELLO - 我不關心的指針 - 我該如何去回答這個問題, 用戶鍵入了同樣的事情?有什麼必要在這裡?是啊。 [學生]使用的功能。 >>我可以使用一個函數的開箱即用。 我可以使用一個函數調用strcmp,S-T-R-C-M-P, 只是說字符串比較的縮寫形式。 如果我們進入,例如,比較兩對,這是在今天的講義, 我這樣做。 我一直下降到26左右,一切從1號線 現在請大家注意,這部分也發生了一點點。 讓我們忽略了一會兒,第28行只集中在這一個。 我們說什麼(星期一),海峽比較不? 它處理的過程中,在這種情況下,服用2指針,s和t, 排序幾乎把手指放在這2個字母, 必須做的是像一個while循環或循環的東西, ,它說,這是相同的嗎?如果是這樣,將手指或指針向前移動。 這是相同的,這些相同的,這些是相同的, 這是相同的,這是一樣的嗎?而且哦,我在結尾的字符串s和t。 我還沒有發現任何矛盾。是的,這些字符串是相同的。 什麼STR比較的回報,如果兩個字符串是相同的,顯然是嗎?零。 所以0是很好的,因為如果在這種情況下,則返回-1或+1, 這意味著,只是發生之前按字母順序或在t。 為什麼會是有用的,它告訴你有一個函數的字符串之前 後,在一本字典嗎? [學生]搜索。 >>搜索和排序。 所以,你可以做的事情,如的二進制搜索或泡沫排序或歸併排序 你要比較的東西。 到目前為止,我們已經削減某些角落,只談到排序 的背景下的數字,因為它是好的和簡單的說說, 但你一定可以比較字符串,蘋果,香蕉, 因為如果蘋果被稱為到來之前,香蕉,同樣, 你可以將字符串大約在內存中一樣羅布與歸併排序的視頻 我們在這裡所做過的舞台上,選擇排序,插入排序,冒泡排序。 所以我們可以採取什麼地方?讓我們來試試這個。 讓我們的忘記了一會兒,這個教訓,嘗試和複製1.C做到以下幾點。 我說在第21行打印的東西, 然後我得到了來自用戶的字符串, 然後我檢查了。 我們還沒有真正得到這個習慣,但現在,讓我們做到這一點。 實際,讓我們剝開這層。這是真正的char *。這傢伙是真正的char *。 所以,這是什麼意思進行檢查,如果S == NULL? 事實證明,當你調用一個函數一樣的GetString 或更一般只要求一台電腦給你一些內存, 東西可以去錯了。 你可能是瘋了,問TB的內存的電腦 問萬億字節的內存,只是不存在於電腦, 但GetString和其他功能的大喊大叫,你需要通過某種方式 如果你問太多。 的GetString這是,如果你要求更多的內存 比在電腦上,即使這是超級,超級的低概率 因為我們要輸入一個萬字符,然後按下回車鍵, 但概率很低,儘管它可能是,但我仍然要檢查,以防萬一, GetString時,回答等功能,返回的特殊值, 如果出了問題是NULL全部大寫。 什麼是空? NULL恰好表示指針。它的內存地址為0。 世界決定意,如果這是我的電腦的內存 - 你知道嗎? - 我們要偷的每一台計算機的內存只有1個字節,這是位置0。 我們要去給它一個暱稱為NULL,我們要保證 ,我們永遠不會真正把真實的數據 因為我們只是任意需要一個特殊的值,又名NULL,0, 因此,我們可以大聲喝斥用戶,如果出現錯誤。 否則,你可能不知道0意味著把這裡的東西 或它意味著出事了嗎? 我們都同意,返回NULL意味著什麼, 沒有實際地址返回。 現在,在這裡我只是通過我的人的慣例,我返回1,從主 如果出現錯誤。 這是因為主要的回報的約定是返回0,如果好, 或一些其他的值,如果壞。 但是GetString和交易功能,在內存中返回NULL,如果出現壞。 好吧。不幸的是,第27行,超級簡單,但它是完全無法複製的字符串。 為什麼呢?我們可以看到如下。 我要求在27行s的副本,並呼籲它噸。 所以我不會問用戶時間2串;我只是說在s 應在T。 所以,現在只是證明這是多麼破碎,第29行起,我在做什麼? 首先我檢查如果t的長度是大於0的。 有一些字符串。用戶輸入的東西英寸 第32行,顯然是什麼? 聽不見的學生回應] >>權。您可以推斷,從我說的做。 但在技術上,這是什麼做的? T [0]代表什麼? [學生]:第零個字符。 >> [馬蘭]第零個字符。 或者,更人性化的,在T的第一個字符,不管它是什麼,H,也許在這種情況下。 和toupper做什麼它說。它利用第零個字符的T和它改變它。 因此,這意味著第零個字符的T,大寫, 在相同的位置把它放回去。 所以,如果我鍵入Hello小寫字母,這應該改變小寫h資本H. 但問題是,在35和36什麼,我做的是打印出我們的s和t。 你的直覺是什麼? 我究竟要什麼,如果我輸入了全部用小寫嗎? 這是怎麼回事,列印嗎? >> [聽不見的學生反應]“那是什麼? [學生]:大H,其餘小。 >>大H,其餘小的,S或T? [學生]兩個。 >>兩種。沒錯。所以,讓我們來看看這裡發生了什麼事情。 讓我去和編譯。這是COPY1,所以COPY1。好的。 放大,讓我繼續運行COPY1,輸入,想說什麼:您好,小寫字母。 資本化的副本,但它顯然資本化原, 因為現在發生在這個故事嗎? 在第27行,其實我不似乎被複製的字符串, 但即使你可能直觀地希望的情況下, 如果你仔細想想這張照片,我真正做了什麼? 一半的圖片是相同的。 因此,讓我們回滾的時間,使噸尚不存在的故事。 S可以存在的故事,但讓我們小寫您好,這時間。 因此,讓我解決了我的實際輸入數字。 在這種情況下,在這裡,我們有H-E-L-L-O。 我們將以此作為一個字符序列,在這裡把我的分割線,我的\ 0。 因此,這是我們在哪裡,只要1號線24上下的,給予或採取,已執行。 這是我記憶中的畫面。 當我到第27行,會發生什麼呢? 就像以前一樣,我得到一個指針,我會畫這個廣場。 這就是所謂的T。默認情況下,它的價值?誰知道?一些垃圾的價值。 因此,我將抽象為一個問號。 盡快右手邊的第27行執行,我把裡面的T? 同樣的事情,在s。 因此,如果我們的時刻刪除這個抽象的箭頭和我們說, 哦,這是內存加載地址123,當你說T得到s,分號, 你從字面上把123在這裡。 現在,如果我們種簡化我們的世界再次與圖片, 你真的做的只是另一個箭頭可以使你的世界 從t到指向完全相同的字符串。 所以,當我在31和32號線去改變T [0], 什麼是T [0]顯然與現在的代名詞嗎? [0] 所以這一切的發生。 即使這種感覺有點低的水平,神秘的 這種感覺就像也許是直觀的,這應該只是工作 - 我複製的東西,它只是工作 - 如果你真的覺得什麼真的是一個字符串,它是一個char *。 嗯,那是什麼?這是一些字符的地址。 然後,也許更有意義,當你嘗試做一些事情 超級看似簡單的這樣,你做的是複製一個內存地址。 你的字符串本身實際上沒有做任何事情。 所以,即使你不知道你將如何解決這個問題的代碼, 高的水平,從理論上講,是什麼,我們需要做的,以使TA s的真實副本,顯然嗎? 是啊。 >> [學生]給它一個新的位置嗎? “沒錯。 我們需要,給T A品牌新的位置。 我們需要以某種方式創造的世界中,我們得到了一個新的內存塊, 這只是為清楚起見,我會畫右下面這一個,但它並不需要在那裡。 但它需要是相同的大小,所以我會吸取這些垂直線在同一個地方。 這是罰款,如果最初全部是垃圾。誰知道是什麼嗎? 第1步將有盡可能多的內存給我,因為我需要 適合的副本招呼,然後找出如何複製的H這裡,這裡的電子, 升這裡,等等。 但是,這已經覺得有點明顯,即使一些細節仍是抽象的。 這個字符串複製到這一點,它只是一個for循環或while循環 你變得更熟悉的東西。 所以,讓我們來試試這個。讓我進入copy2.c。 在copy2.c我們具有幾乎相同的程序,除了第27行。 它看起來有點複雜,但如果我們把它分解一塊一塊的, 的左手側是相同的。 字符* T在內存中創建了這件事情,但一個問號 因為我們不知道什麼是有默認。 在右手邊,我們現在引入一個新的函數malloc的, 內存分配的,給我的記憶, 它顯然需要多少個參數,括號裡面的東西有多少? 我聽到怨言,1和2,但它僅僅是1。 有沒有逗號,這意味著僅有1括號內的事情。 即使有其他括號,我要強調 最外層的括號裡面是什麼,它是這個表達式: (strlen的()+ 1)* sizeof(char)的的。 因此,如果我們真的該好好想一想,這是說給我s的長度。 我為什麼,雖然,加1到的長度? >> [聽不見的學生反應] 沒錯。我們需要空間,這傢伙的尾巴,有沒有英文的意思第六個字符 但確實有特殊的綱領性意義。 所以我們需要一個+ 1,因為人意料的strlen返回的長度, 打招呼或5,它不給你額外的空字符。 所以,我手動添加+ 1。 然後這個,*大小(字符),我們還沒有看到這樣的情況。 這不是技術上的功能。 這是一個特殊的關鍵字,它只是告訴你的計算機上的某些數據類型的大小是 因為在現實中,我們中的一些人有32位計算機。 我有一個很老的電腦在家裡,它僅使用32位來表示指針。 所以,如果我做的數據類型的大小,它可能是32位。 但是,如果我用我的新奇特的電腦,我可能會得到64位值 類似地址。 因此,在這種情況下,僅僅是超級安全,我們不打算到硬編碼類似的東西 - 那麼,究竟是根據什麼說了這麼遠的一個字符的大小嗎? 我們已經差不多口頭上說是1個字節,這幾乎是全線。 但同樣,假設往往是壞的。 他們導致bug的軟件,如果人們使用軟件的方式,你不打算。 因此,讓我們的抽象之遙,只是更一般的說 我需要很多的內存塊 並且每個塊的存儲器應該是相當於一個字符的大小, 這是在實際上等於在此情況下為1,但它是一個更通用的方法將其寫入。 因此,如果這個詞是個招呼,多少字節的malloc顯然是分配給你好呢? [學生]六。 “六。正如很多,因為我們有問號在屏幕上。 然後採取的猜測現在根據你的理解的GetString 可能是什麼的malloc返回? >> [學生]的地址。 地址是什麼?第一塊內存。 我們不知道那裡有什麼,因為其他一些功能 已使用內存之前。 但malloc的,喜歡的GetString,返回地址的第一個字節的內存 它已經為你留。 然而,它不會做一個反斜杠空字符填補這個空白 因為事實證明,你可以使用malloc分配的任何整數,字符串,數組, 花車,學生結構。 您可以使用malloc完全通用。 它不關心或者知道你分配內存。 因此,這將是放肆的malloc把\ 0 在每一個內存塊,它給你 因為\ 0的字符串的事情僅僅是一個慣例。 它不使用int類型,它不使用的花車,它不是供學生使用。 這樣一來,用malloc是疑難雜症的負擔是完全在你的程序員 記得多少字節分配,而不是以往任何時候都使用一個for循環 或while循環的邊界的內存塊,你已經走過去。 換句話說,只要你分配內存, 你不能要求操作系統,哦,順便說一下,有多大的內存塊是這樣的嗎? 這完全取決於你要記住,如果你需要的值。 因此,讓我們來看看如何我繼續使用該內存。 在28和29號線,我為什麼這樣做呢? 只是總的仔細檢查。 以防萬一出事了,我問一些瘋狂的內存量 或我有這麼多的事情在計算機上運行,根本就沒有足夠的內存, 那樣的話,我至少要檢查是否為NULL。 在現實中,大多數計算機給你的幻覺,每一個程序 可以使用全部的RAM, 但即便如此,如果用戶在一些瘋狂的長字符串,也許是因為他們是一個壞傢伙 他們實際上是想你的程序崩潰或攻入, 你至少要檢查返回值的malloc和是否等於null。 如果是這樣,就讓我們現在退出,因為我不知道該怎麼做,在這種情況下,。 如何複製的字符串?有一些方法來做到這一點。 有STR功能在C複製,但它是超級簡單的,我們能夠做到這一點,老式的方法。 首先,讓我弄清楚什麼s的長度。 我可以把這個循環中的,但我只是把它在這裡為清晰。 所以N存儲原始字符串的長度,這顯然是5。 然後在我的for循環,我迭代從0到n, 在每次迭代我把[]內為t [I]。 所以,這就是我暗示,我的手指在琴弦前。 由於for循環遍歷這個樣子,我要被複製h進這裡, E到這兒的時候,到這裡,因為這是,這是T。 那麼最後,在第35行,為什麼我這樣做嗎? 我需要確保我結束的字符串t。 我這樣做,是這樣是超級明確的。 但提出,一個人,如果你能這樣做,以不同的方式。 我並不真的需要35行。有另一種方式來做到這一點。 是啊。 >> [聽不見的學生反應] >>說它響亮。 [學生]小於或等於。 “沒錯。 我們只能說小於或等於n,它一直不好一般 因為我們幾乎總是等於我們要計算的東西 我們去太遠。 但請記住,我們多少字節分配? 我們分配的strlen的S,5 + 1共6個。 因此,在這種情況下,我們可以做這樣的事情 這樣我們就複製不只是打招呼,但在“\ 0”在最後。 另外,我們可以使用一個功能稱為STR副本,STRCPY, 但不會是幾乎一樣多的樂趣。 但是,這是它的引擎蓋下方。 最後,我們像以前一樣做同樣的事情。 我利用T然後我要求原來看起來像這樣的副本看起來像。 因此,讓我們試試這個。讓我在這裡。請COPY2。我們會放大在,並運行COPY2。 我要輸入小寫字母,而事實上我得到小寫的原始 但資本你好的副本。 但我沒有這樣做,只是還沒有。我要在這裡做最後一件事。 46和47顯然是釋放內存,但是,實際上是什麼意思呢? 我在做什麼,你認為,通過調用第46行和第47行嗎? 什麼樣的影響?是啊。 [聽不見的學生回應] >>沒錯。 你只是告訴操作系統,嘿嘿,感謝這個內存。 現在,您可以用它給別人。 這裡是一個很好的例子,垃圾值。 我剛才用這個記憶寫下來的單詞hello在2個地方, 這裡,這裡,這裡,和這裡。 因此,這是H-E-L-L-O-\ 0。 但後​​來我打電話第46行和第47行,你知道會發生什麼的圖片嗎? 其實,等待,這張照片是舊的。 一旦我們的副本,這傢伙居然指指點點, 讓我們刪除的數字,只是抽象掉,因為我們的箭再次。 這幅畫中會發生什麼,當我打電話免費? [聽不見的學生響應>>甚至沒有。 如果我打電話s和t - 樣的一個棘手的問題 - 這幅畫不改變 因為調用s,並呼籲只是告訴操作系統, 哎,你可以使用此內存,但它並沒有改變為null 或一些特殊的字符,它不改變這一點, 它不改變H或E或L或升或o在別的任何地方。 的圖片,只要你通話完全免費,沒有任何變化。 ,這其中就有原產地的垃圾值,因為如果我再在這個程序 要求更多的內存GetString或malloc或類似的操作系統, 和操作系統的說,當然,我有12個字節的內存剛剛釋放, 使用這些方法,你有什麼要交嗎? 你要交給一個內存塊,我們通常會畫 帶問號的,但這些問號是什麼? 他們正好是H-E-L-L-O,H-E-L-L-O。 這是我們的新的垃圾值,只要你釋放該內存。 這裡也有一個現實世界的含義。 這恰好與RAM,但您的計算機 其實做同樣的事情磁盤。 我們再談談,特別是與未來的問題集中在取證集。 但到底發生了什麼,如果你有一些敏感的財務文件在您的桌面上 或一些粗略的JPEG和將其拖動到您的垃圾, 當你把它拖到垃圾桶或回收站時,會發生什麼情況? 你知道我在說什麼。 [笑聲] 當你的證據拖動到回收站或垃圾桶,會發生什麼情況? [聽不見的學生反應] 好了,所以小心。當你這樣做,會發生什麼情況? 簡短的答案是什麼,對不對? 粗略的或敏感的文件仍然只是坐在那裡,在您的硬盤驅動器上的某個地方。 我們大多數人至少已經了解到硬盤的方式,你需要清空你的回收站 或回收站刪除的文件。 事實上,當你右鍵點擊或控制單擊您的垃圾 或選擇“文件”,“清空廢紙簍”或任何 你實際上是空的垃圾桶或回收站,到底發生了什麼,然後把這張照片嗎? 更多的什麼都沒有。所以沒有什麼實際發生的磁盤上。 如果我們僅僅是暫時偏離和寫 - 我會使用後面的。 所以,現在的故事正在發生變化,從RAM,這是程序存在 而你在運行當中,磁盤,這是他們長期存儲 即使在電源熄滅,現在 - 而且在未來,我們會回來的這 - 讓我們假裝這代表您的計算機硬盤驅動器內 因為在這一天,他們曾經是圓盤,就像軟盤。 所以,如果你有一些敏感的Excel文件,它可能需要此內存塊的 您的計算機的磁盤上,我只是畫相同的任意1s和0s。 當你拖動的文件,如你的垃圾回收站, 從字面上沒有任何反應,因為蘋果和微軟剛決定 垃圾桶,回收站實際上只是一個臨時佔位符。 也許最終的OS將它清空你的,但通常情況下,它不會做任何事情, 至少要等到你的空間是非常低的。 然而,當你去清空垃圾箱或清空回收站, 同樣,什麼也沒發生這個畫面。 所有這一切發生在您的計算機上的其他地方,有一些類型的表。 這有點像一個小小抄說,讓我們的說,resume.doc的, 所以你的簡歷在Microsoft Word文件,用於住在你的硬盤上的位置123, 在內存中,而不是在RAM,但在您的硬盤, 粗略JPEG住在456,和住在789或是其他地方,您的Excel文件。 當你清空垃圾桶或回收站,刪除的文件 這幅畫並沒有改變。在您的硬盤驅動器上的“0”和“1不要去任何地方。 但這個表,這個小數據庫的各種變化。 當你刪除你的簡歷,這是因為雖然在一定程度上被刪除的文件, 但所有的電腦沒有忘記那件事住在您的硬盤驅動器。 您的簡歷或任何其他文件的0和1組成仍然完好無損。 所以,如果你這樣做是偶然,還是有一個非零的概率 使用Norton Utilities或一些商業軟件,你可以恢復你的數據 在生活中,其目的是找到“0”和“1”,有幾分被孤立, 被遺忘在這裡,但離開這裡,這樣您就可以得到您的數據備份。 或與警方或聯邦調查局的法醫調查將採取實際的硬盤驅動器 真正的“0”和“1,看像JPEG文件,看起來像Excel文件的模式, 和恢復,即使電腦已經忘記了他們有他們的方式。 因此,唯一的辦法真的要刪除數據,我們將討論在未來, 是進行擦洗或擦拭的文件或硬盤 - 你真的不能擺脫的0和1 否則你會從一個GB的硬盤驅動器 和你最終會與一兆字節的硬盤驅動器,如果你不斷地被刪除, 從字面上看,“0”和“1。 所以,你會怎麼做,如果你真的想掩蓋你的行跡 的根本問題仍然是,有0和1的磁盤上的? 我看到有人指手劃腳,你會實際打開的設備。這將工作。 [笑]但如果這是一種昂貴的解決方案,你會是更合理? 是啊。 >> [學生]覆蓋它們。 >>覆蓋他們什麼呢? >> [學生]其他數據。 其他數據。您可以只是簡單地覆蓋你的磁盤0或1或全0,全1。 這的確是一些軟件的作用。 你可以購買軟件,甚至獲得免費的軟件, 甚至建到Mac OS這些天來,因此在Windows, 是能夠安全擦除。 其實,如果你想今天所有的跑回家,如果你有一個蘋果,這樣做, 如果你有一些東西在你的垃圾,你可以做“安全清倒廢紙簍”, 這正是這麼做的。 而不僅僅是擦除文件,它不會刪除“0”和“1, 相反,它只是改變了他們所有的,例如,0,點,點,點。 因此,你的未來的pset實際上是有意恢復數據 - 我們已經採取了在校園內的人,地,事,物的照片, 為此我們做了法醫圖像的數碼相機的存儲卡, 這是同樣的想法 - 你將面臨的挑戰是找到 的模式,代表您的硬盤驅動器上的JPEG, 很像以前的學生,他的電子郵件,我讀了幾個星期前做 恢復他的妹妹的照片。 為什麼我們不採取有5分鐘的休息時間,和我們會重組與更多的內存。 因此,這裡的事情變得有點令人費解,但是這是一個非常強大的步驟 對理解這項工作的。 這裡是了一項名為pointers.c。 這是在今天的示例代碼。 請注意,在第幾行,19至22日,所有我們正在做的是類似的GetString 並返回一個地址,將其存儲在s。 今後的pset甚至3,如果你想要的,但pset的4和 在那裡你可以開始把這些培訓驅動輪離開自己, 沒有任何理由假裝字符串不存在了。 這當然是好剛開始說的char *。 順便說一句,在網上參考和書籍,你可能會經常看到旁邊的星號的變量。 你甚至可能看到它的左右兩側的空間。 所有這些都是功能上是正確的。 不過,就目前而言,我們將這種方法的標準化,使超清晰 ,char *是這樣說的字符指針。 這是數據類型。 的名稱,然後在這種情況下,該變量為s。 因此,我們已經得到了一個字符串,我們調用它s。 然後在這裡發現,其實我做的一點點的掛羊頭賣狗肉。 這就是所謂的指針的算術運算,這是超級簡單的排序。 這只是意味著增加和減少數字的指針。 但是,這實際上是工作的。 這個方案顯然打印字符串的第1個字符,每行這樣最終的結果 - 正是這樣,我們可以盡情這是怎麼回事,使指針,運行指針,讓我放大。 現在,讓我像HELLO類型輸入類型 並打印出每行1個字符。 直至一秒鐘前,我們就已經做到了這一點用方括號表示。 我們希望有一個for循環,我們會做的printf的s [i]和我們做一遍又一遍 用反斜杠n在每行末尾。 但這種方案是不同的。這個程序使用,從字面上看,算術。 所以這是怎麼回事呢? 首先,這個循環執行之前,是什麼,僅僅是明確的,是什麼呢? S是嗎? >> [學生]的地址。 >>地址。 它的地址,在的情況下,你好,這個詞的第一個字符,這是H。 因此,s是,在這個特定的例子中,h的地址。 那麼,是什麼意思做s +我嗎? 嗯,我從0開始,在for循環。我們已經做了很多次。 我是要去的字符串的長度,顯然。 因此,在此循環的第一次迭代中,i是明顯0。 所以這個表達式是說S + I - 而,S +0,顯然只需s。 那麼,什麼是*嗎? 現在,我們在一個稍微不同的方式使用明星。 讓我繼續前進,擺脫對的,因為我們正在談論t和s的副本。 現在,我們只是想講一個故事,涉及小號。 因此,在這一刻,後字符串類型的,我們的世界看起來很喜歡它以前 只需s h和存儲地址通常指向的字符串你好。 如果我現在做的像一條線*(S + I),讓我們嘗試了這一點。 所以*(S + I)。讓我簡化了這一點,因為這是0,所以這是*(+0)。 好了,等待一分鐘。進一步簡化。這是*()。 那麼,現在的括號是種愚蠢的,所以現在就讓我們做*。 因此,在這個循環中,該行突出顯示,26的第一次迭代中, 幾乎相當於印刷本。 *的數據類型是什麼? 在這方面,因為明星恰好是旁邊的s本身, 但更特別的是,因為我們不再聲明, 我們不創建一個變量了,這裡沒有提到的char *在第26行, 這裡沒有提到的關鍵字串,我們只使用一個變量稱為s, 事實證明,現在的明星都有稍微不同的,無可否認,撲朔迷離的意義。 *在這裡的意思去做,就這樣在s和打印的地址。 所以S是在這裡,s是 - 有點像槽和梯子,按照箭頭 - 在這裡。 因此,這是* S。 那麼,什麼被印在第一次迭代中,第26行的循環? 我打印出來%,這是一個字符的佔位符, 然後一個\ n新行。 *(S + i)其中i為0就是這種。 所以char類型,我將在%C? H. 在接下來的迭代循環 - 你或許可以看到這是怎麼回事 - 明顯的下一次迭代i是1,所以這意味著s +1個 ,那麼現在我需要括號,因為現在的明星需要說 到內存地址+1。 是什麼?我們走的時間和說,現在這個箭頭是不實際做我們任何好處。 讓我們更具體的說,這是存儲數量123 此字符串的開始,因為你好,這是地址123,這是124,等等。 因此,在第二次迭代時,我說S +1,這是喜歡說123 +1, 否則為124,所以char類型被印在第二次迭代? E在內存地址124。 +再次,125,126,127,和這個循環謝天謝地停止之前,我們在這裡 因為我使用strlen,以確保我不指望太高。 所以這也是它。 再次,這是就好像我們做了一個星期前。 讓我把它寫在下面的行,即使我們不希望做兩件事。 這是相同的,現在這個。 因此,即使s是一個字符串,因為我們已經調用了幾個星期,S是真的一個char *。 因此,如果我們想成為超級肛門,這是很正確的寫特定的字符 在第i個位置使用這些數字的地址,這星算, 但坦率地說,這就是這麼多的清潔劑。因此,這是不壞的。 沒有理由停止在這裡做線27,26在功能上是相同的, 它的功能相同的確切原因,我們一直在討論迄今。 最後,29是良好的做法。 調用free s的,現在你給GetString的給你的內存 這還是因為同樣的原因,我提到週一,GetString的幾個星期 已經被引入到您的代碼中的錯誤。 你的代碼為週有內存洩漏 讓你一直問GetString的內存,但你從來沒有給它。 而且,我們特意選擇了教學法 因為它只是太多認為大約在早期。 但現在我們需要更多的對稱性。 如果你問電腦的內存,是為getString的情況下, 的malloc的情況一樣,顯然, 現在,您必須pset的4起,也無任何這樣的記憶。 請注意,這是不同的,說廉政n。 你不需要釋放,因為你沒有調用GetString 你沒有調用malloc。 而且,即使你叫調用getInt,因為我們最終會看到, 調用getInt不分配內存給你,因為你可以傳遞的整數 花車和字符的方式,我們已經做了好幾個星期。 字符串,雖然是特殊的,因為實際上他們的串聯多個字符。 因此,他們只是不同的字符和浮點和整數等。 但我們會回來的,不久。 任何問題,然後在此開始的指針嗎?是啊。 [聽不見的學生問題] 啊,非常好的問題。 C實際上為你做的幾件事情之一,這是方便, 它計算出你的數據類型的大小是什麼 ,然後做那種對你的乘積。 中字符的情況下,這是不相關的,因為幾乎總是一個char是1個字節, 所以這只是工作。 但為了討論的方便,如果你在實際打印整數 你試圖打印出一些值,指向一個整數, 你同樣不會需要做的+ 4 *我只是因為int是4個字節。 指針的算術平均值的C編譯器為你做所有的數學。 所有你關心的是點樣的人的感覺。是啊。 [學生]如果你聲明一個字符串在一個for循環,你必須釋放它嗎? 這個問題問得好。 如果你聲明一個字符串內的循環,你需要釋放它嗎? 您只需要你GetString或使用malloc分配的可用內存。 所以,如果你只是這樣說 - 讓我把花括號,因此,所有的代碼是有關。 如果你做了,儘管是buggily的,像這樣的char * T = S, 你不需要免費的T,因為T不涉及任何提及malloc或GetString的。 GetString時,如果通過對比,你這樣做,那麼,你將需要免費的T。 而事實上,你唯一的機會做到這一點是在這個循環中,對同一問題的範圍 我們已經討論了過去。 否則,你會被分配內存,分配內存,分配內存, 和在程序結束時,因為你以外的該循環, t不存在的,但你從來沒有告訴操作系統 你並不需要的內存了。 不久,pset的4或5,我們將裝備你的程序稱為Valgrind的, 這是類似的,它是一個神秘的界面得到了一定程度的精神,GDB, 但它的目的是幫助你在生活中。 和Valgrind是一個程序,將在未來搜索你的程序 查找內存洩漏,無論是從GetString或malloc的, 我們將開始使用更因為我們停止使用盡可能多的CS50庫。 現在我們終於有幾分的詞彙和理論模型中的那種精神 解決這個破碎的程序。 因此,在這個破碎的計劃內的交換,交換, 但它從來沒有真正的工作,主要是因為主要通過在X和Y,召回, 和那些被傳入的值,可以這麼說。 副本交換。 年底的交換,確實被交換a和b, x和y,我們討論(星期一),但當然不在場。 所以我在這裡提出的綠色,這其實是這裡的解決方案。 而實際上,讓我感動我的星星,只是是一致的 ,即使再次,功能這並不重要。 在未來幾週,我們將解釋時,為什麼它很重要。 因此,在綠色現在是一個解決方案。 坦率地說,它看起來一大堆混亂的,因為我有所有的這些明星。 讓我指出一件事。 最上面一行在這裡說* A * B 從根本上做同樣的事情,因為它總是。 聲明的參數或參數交換, 第一,這是一個int指針, 其中第二個是一個int指針調用b。 在這一點上是新的唯一的事實是,有一個明星。 這是什麼意思呢?是不是int,b是一個int。 A是一個int和b的地址的地址是不同的詮釋。 在這裡,這是我承認C得到混亂。 現在我們使用的是一個明星,但在這種情況下有不同的含義。 因為我們並沒有聲明函數指針,因為我們是在這裡, 在這裡,我們提領的東西。 所以,在技術上,在此上下文中的第一,第二,和第三線的內部的交換星級 被解引用運算符,它只是意味著去那裡。 因此,正如我的手指跟著箭頭為h, *的手段去該地址,找到我的int類型的存在。 * B表示的地址和那裡的東西遞給我。 因此,讓我們重新繪製的圖片(星期一)現在使用的棧幀, 其中一個的底部將是主要, 上其中之一將是交換, 所以,我們的世界看起來,就像週一,是這樣的。 這裡是一大塊的內存,主要是要使用。 回想一下,該計劃有2個變量, 一個叫x和一個稱為y,我已經把數字1和2,。 現在,當我打電話交換一樣,我(星期一) 以前我用的是紅色版本的這個程序時,它看起來像這樣, 我有2個參數,a和b,並沒有寫在這裡和這裡? 僅有1和2中,x和y的字面複製。 今天,我們改變這種狀況。 今天,而不是傳遞int類型A和B,我們要通過2個地址。 這些地址正好為整數,但這些地址不是整數。 他們的地址。它像是一個郵寄地址。 所以,現在我們需要的只是給自己多一點細節在屏幕上。 這是我的電腦的內存,因為它整天。 現在,我們需要一些任意的編號方案。 因此,讓我們說,只是偶然,這是內存地址123,124。 讓我們只說這是125,這是126,等等,但那是完全任意的。 我們只是需要一些在我的記憶中編號方案。 所以,現在當我通過在X和Y,我不打算通過在X和Y; 我要通過郵政地址,可以這麼說,x和y的 從而使被存儲在這裡和這裡是1和2, 但如果你能看到我的小文本,通過在這裡和這裡得到什麼? [聽不見的學生回應] >>沒錯。 123被放在這裡,和124被放在這裡。 現在,因為我用本的第一行,在這裡的明星在上面, 我只知道,123和124,儘管它們顯然整數 任何人類可以注意到,他們應該被解釋為地址,數字地址。 他們不是在和自己的int類型,他們的地址, 那是因為我已明確地把星星。 所以現在我的第一,第二和第三線的實際代碼,這裡發生了什麼? 讓我們繪製的圖像的其餘部分。 TMP就像是在星期一。沒有什麼特別的TMP。 這是本地32位變量,和裡面的,我的一個顯然的值存儲。 現在,如果我剛才說的TMP = A,那麼我放在這裡? >> [學生123。 123。但是,這不是我在做什麼。 我說的TMP = * A。星號表示去那裡。 因此,這裡是123。我怎麼去那裡?假裝有一個箭頭。 好了,就在這兒,1。那麼,什麼被存儲在tmp,顯然是嗎?僅有1。 所以,換句話說,tmp是去的地址,目前正處於一個*,*的手段, 這顯然是123。 好了,在這裡,我們是在位置123,我看到數字1, 所以我打算把1號。 現在,我該怎麼辦第2行中,* = * B嗎? 這是稍微複雜些,因為現在是一個什麼呢?這是123。 所以,一個是在哪裡呢?在我之前。所以去那裡。好吧。 現在,最後,然後終於,這將開始有意義,希望, * B在B意味著什麼? 124。因此,我需要去那裡,這是2。 那麼,我該怎麼放哪裡? 2進入這裡,因為進入* A * B。所以,我會做到這一點。 你已經可以看到,或許,我們更接近 第一次正確地解決這個愚蠢的,簡單的問題 因為現在我們仍然是x的回憶, 我們有2個副本,無可否認,y的, 但現在3號線* B說。 因此,這裡的B。 * B的手段去那裡。那麼,是位置124? 它顯然是在這裡。所以我把什麼呢?顯然,tmp目錄。 所以,現在我做到這一點。所以,我這裡這裡。 而現在所有這一切,123,124,和1? 只要交換的回報,這種記憶丟失 因為一旦作為交換的回報,操作系統 在未來再次使用該內存。 只有主內存在這個所謂的堆棧的底部,堅持圍繞。 因此,我們現在終於有一個工作版本。 讓我去為swap.c,並注意以下幾點。 在頂部的程序,我已經改變了我的原型是* A和int * B。 因此,唯一的事情,我改去,這是壞的,從紅色到綠色,這是很好的, 是我今天的這些明星。 但再往下在這裡交換本身我不得不複製,粘貼只是在幻燈片上。 我在這裡有一個明星,明星在這裡 - 相匹配的原型 - 然後所有這些事情現在有星星除了TMP 因為使用一個臨時變量,有沒有什麼新東西。 我只是需要臨時存儲類型為int的。 因此,我們並不需要一個明星。 我們需要的只是明星,這樣我們就可以過這種任意邊界 這些在我的電腦的內存中的2幀之間。 但最後一件事必須改變,你可能已經瞥見了它。 什麼其他的顯然是不同的呢? >> [學生]&X。 是啊,所以25是最後一行的代碼,我需要改變這個工作。 一個星期前,即使是在星期一的第25行是這樣的,交換x和y, 這是剛剛打破,因為如果你說掉期(X,Y) 你給的x和y的副本掉,然後做自己的事情, 但你從來沒有真正改變x和y本身。 所以,即使你從來沒有見過這個字符與符號的代碼, 只是猜測。符號做什麼,顯然是嗎? [學生]的地址。地址>>注意到。 因此,符號是說給我x的地址。 誰知道它在哪裡?它正好是123。我不在乎。只要給我x的地址。 &y表示y的地址給我。 在這一點上的故事是完全一致的圖片,我們剛才畫。 所以,我得承認指針,當然對我來說,當我第一次開始學習, 絕對包住我的腦海裡約最困難的事情之一。 但實現,尤其是我們玩這些事情, 智力無趣的,如果你把它分解到這些超級簡單的排序問題 移動數字周圍,回答了很多混亂的指針 真的可以來自這些非常基本的力學。 這裡有一個地址。去那裡的明星。 或者反過來說,這裡是一個符號。圖的地址實際上是什麼。 好的。 那麼,此內存來自哪裡? 我們已經開了幾次這張照片,我一直許諾我們會回來的, 但這裡是您的計算機的內存中的代表性 這是多一點比我們的黑板標記。 在頂部的文本段代表你的程序是什麼? [聽不見的學生回應] >>你說什麼?再說一遍。 [學生]:實際的程序。 >>實際的程序。 因此,“0”和“1您已經編寫C代碼編譯後,然後運行鐺 和產生0和1的目的還是藏在內存中 因為當你雙擊一個圖標在您的Mac或PC 像馬里奧或運行命令提示符,從磁盤0和1的 獲得加載到內存中,計算機可以操縱他們 更迅速地執行。 所以初始化的數據和未初始化的數據,我們不會多談這些問題, 但這些僅僅是全局變量。 初始化是指全局變量,你給的值; 未初始化意味著,你沒有給的值的全局變量。 然後這些環境變量,我會完全揮揮手, 但他們在那裡和存儲事情,比如你的用戶名 和其他類型的低級別的細節。 但最精采的作品是這件事情的棧和堆內存的佈局。 堆棧中再次是明確的,是的函數被調用時使用的內存, 每當有局部變量 ,每當有參數被傳遞。 所有這些都發生在堆棧中。 堆,我們還沒有談到,但猜測誰使用堆。 只是不同的內存塊。 它發生在被繪製在頂部,但是這是一個任意的圖案公約。 誰的顯然已經使用的內存從堆中週嗎? 這是技術上你,但間接的。 >> [學生] GetString的。 GetString和malloc的。因此,這裡的根本區別。 你知道,在過去的幾個星期,如果你需要的內存,只需要聲明一個變量。 如果你需要大量的內存,直接在你的函數聲明一個數組。 但我們已經把面臨的問題是,如果你聲明的變量在本地內的功能, 只要在函數返回,會發生什麼變化記憶體及變量? 只是它不再是你的,對不對?它只是消失在概念上的排序。 它仍然是物理存在,很明顯,但它不再是你的使用權。 這顯然是有問題的,如果你想在生活中寫功能 實際分配內存,不給它立即返回。 舉個例子:在生活中的GetString的目的是不知道提前 我要在鍵盤上輸入一個字符串有多大, 但它有能夠分配內存來存放大衛你好 或213-248,用戶可能會鍵入。 所以GetString的已使用malloc。 malloc的,因此必須使用的堆棧; 而不是它的使用這個東西稱為堆。 有沒有什麼不同的內存。這不是更快或更慢或類似的東西。 這只是身體在不同的位置。 但是,該規則是在堆上分配的內存的 你將永遠不會被帶走,直到你調用 - ​​猜測 - 免費。 與此相反,任何在棧上的內存,你問的只是聲明一個數組 或者聲明一個變量,如我們已經做了好幾個星期, 默認情況下,結束了在堆棧中。 的偉大工程的90%的時間,但對那些罕見的場合 在那裡你要分配內存,並保持周圍, 然後,你需要使用的malloc之類的函數。 我們使用GetString時,在使用malloc之類的函數。 讓我們來看看,這可能分解,然後採取偷看在賓基。 我們會回來的,在未來。 這是一個超級簡單的程序,在第2行做什麼? 在英語中,這些第2行代碼裡面做的主嗎? [聽不見的學生反應] 小心點。它並沒有給我的地址,x或y。 [學生]給出整數的指針。 >>好。給我指向整數的指針。 換句話說,給我2塊內存我保持繪圖今日,, 即使我現在將其擦除,為方形。 給我2塊內存,一個叫X,Y - 剛才我叫s和t - 該內存塊的類型是什麼? 這將存儲地址。 這是int *類型。 因此,一個int的地址最終會住在x, 一個int的地址,最終將居住在y 但最初,x和y的裡面是什麼?誰知道?垃圾值。 它有什麼做用指針。 如果我們沒有把東西,誰知道居然有嗎? 現在,X。這裡發生了什麼?這是合法的,因為x是一個指針。這是一個int *。 因此,這意味著我可以把在x一些的內存塊的地址。 什麼的malloc返回?完美的,它返回地址, 在一個整體的內存塊的第一個字節的地址。 多少個字節,這顯然是分配,例如,在家電嗎? 什麼是一個int的大小嗎? 4。 如果你覺得回到了1週,這是超級重要的,永遠記住, 但在這種情況下,它是有用的知道,4個字節。 因此,這是在堆上分配4個字節 和它的返回地址的第一個我任意。 現在,X是什麼做的? A * X = 42是做什麼的? 如果我們的故事在這一點上有X,它看起來像這樣一些垃圾的價值, 這是目前一些垃圾值y的,現在在第3行中,我已經分配了4個字節。 基本上,這張照片看起來是這樣的。 或者更具體地說,如果這是任意地址123,這是我們的故事現在看起來像。 * X = 42意味著什麼呢?這意味著到的地址123,並把42號有。 我不需要畫出這些線條,因為我們沒有做字符串。 我應該寫這樣的,和示範的緣故, 42作為一個int種需要一個很大的空間,4個字節。 所以這是發生了什麼事,但現在有一個問題。 * Y = 13。這是怎麼回事就發生在這裡? 問題是,* Y在我們的簡化的世界只是意味著到y的地址。 在y是什麼?這是一些垃圾的價值。 因此,讓我們假設,垃圾的價值是5551212,發瘋似的。 * y表示去解決5551212。 這就像在這裡。它不存在,例如。 因此,* Y取得13的意思,我想畫13。它不存在。 我已經超過了段的黑板。我能得到什麼? 這神秘的,因為我試圖把在內存中的信息segmentation fault 13日在一個地方,不存在這樣的值。 其餘的程序可能還行,但直至這一點上它不工作。 所以,我們的嘗試講這個故事。 我們會回來的,一旦我們談到十六進制。 讓我們回去,最後,這個東西叫做Binky, 這使人想起坐在家裡玩黏土動畫是斯坦福大學的一名教授, 來講述的正是同樣的程序。 這只是約3分鐘之久。在這裡,我們有Binky。 [男揚聲器視頻]嘿賓基,醒了。它的時間的指針樂趣。 [賓基]那是什麼?了解指針嗎?哦,好極了! [男揚聲器]好了,要開始了,我想我們需要一對夫婦指針。 [Binky]好吧。此代碼分配可以指向整數的指針。 [男性揚聲器]好吧。嗯,我看到了兩個指針,但他們似乎並沒有指向任何東西。 [賓基這是正確的。最初,指針不指向任何東西。 的事情,他們指出,被稱為指針對象,並設置他們是一個單獨的步驟。 [男揚聲器]哦,對的,正確的。我知道這一點。的指針對象是分開的。 呃,怎麼你分配一個指針對象? [Binky]好吧。此代碼分配一個新的整數的指針對象,而這部分設置x為指向它。 [男性揚聲器]嘿,看起來更好。 所以,把它做的東西。 >> [賓基]好吧。 我會取消引用指針x及其指針存儲42。 這一招,我需要我的魔杖解引用。 [男性揚聲器你的魔杖提領嗎?這是偉大的。 [賓基]這是代碼看起來像什麼。我會剛剛成立的數量和... [爆裂聲] [男性揚聲器]嘿,你看,那裡去。 這樣做在x取消引用如下的箭頭來訪問它的指針對象, 在這種情況下,在那裡存儲42。 嘿,嘗試用它來存儲指針,Y 13號通過。 [Binky]好吧。我就在這裡為Y,13號成立 然後採取的魔杖提領,只是... [嗡嗡的聲音喔! [男性揚聲器哦,哎,沒有工作。 再說了,Binky,我不認為提領y是一個好主意 因為指針對象是一個單獨的步驟 我不認為我們曾經做了。 [Binky]嗯,好一點。 [男性揚聲器]是啊。我們分配的的指針y,但我們從來沒有設定它指向一個指針對象。 [Binky]嗯,很細心的。 [男揚聲器]嘿,你看起來好有,賓基。 所以你能解決它的指針對象為x,y點呢? >> [賓基]當然。 我會用我的魔杖指針賦值。 [男性揚聲器]的是,要像以前一樣是一個問題嗎? [Binky]不,這不是觸摸指針對象。 它只是改變一個指針,指向的另一個同樣的事情。 [爆裂聲] [男性揚聲器哦,我明白了。 y點為x的同一個地方。 所以等待。現在,y是固定的。它有一個指針對象。 所以,你可以嘗試的的提領魔杖再次發送13個以上。 [Binky]嗯,還行。這裡“。 [爆裂聲] [男性揚聲器]嘿,你看那個。現在提領對y的作品。 因為指針共享一個指針對象,他們都看到了13。 [Binky]是啊,分享。不管。 所以我們要切換地方,現在呢? [男性揚聲器哦,看,我們沒時間了。 >> [賓基]但是 - [男性揚聲器,只要記住3個指針的規則。 1,基本結構是,你有一個指針,它指向指針對象。 但指針和指針對象是分開的,常見的錯誤是設置一個指針 但忘了給它一個指針對象。 2,指針解引用的指針開始,並遵循其箭頭 訪問及其指針。 我們都知道,這只是工作,如果有一個指針對象, 種回來規則編號1。 3,指針賦值一個指針,並將其更改 作為另一個指針指向相同的指針對象。 因此,在轉讓之後,指針將指向的相同指針對象。 有時,這就是所謂的共享。 而這一切是它真的。再見。 這是Binky。這是CS50。我們會下週見。 [掌聲] [CS50.TV]