[音樂播放] 戴維·J·馬蘭:好吧。 這是CS50。 這是5週的開始。 正如你可能已經注意到, 一些材料 越來越多一點 複雜,小更密。 而且它是很容易的,尤其是當 你已經在習慣了一段時間, 是為了要塗下最 什麼我們做什麼,我們說在課堂上。 但要意識到,這也許不是 理想的教學方法 學習這種物質, 而材料更普遍。 因此,我們很高興 宣布,CS50自己Gheng 龔已開始準備 一個規範的集合票據 用於操作過程中,希望 其是,一個,這些 不僅作為 參考和資源 審查材料中去 回通過材料可能具有的 逃脫你在第一時間左右,但 也讓你的頭可以更 向上比下降,當它 談到時間來講課, 所以,你可能搞 更周到,為 相對於更雜亂。 雖這麼說,你會發現 該網站是這樣的文件,因為這。 並請注意,在左上角,有 不僅表的內容, 而且時間碼的 會立即跳到你 到相應的部分 在視頻網上。 什麼常在這裡做了 在本質上,記載 發生了什麼事在這 特別講座。 和許多的講座是 已經在線使用這個網址。 我們將繼續張貼其餘 那些在本週末結束, 所以不要採取資源優勢。 因此,事不宜遲, 我們開始剝離回 已經作為層 串持續一段時間。 並沒有說什麼一個字符串 上週居然是? 因此,焦炭的明星。 和CHAR星,那麼, 這樣做究竟意味著什麼? 那麼,這一切的時候,如果我們已經 被調用的函數, 喜歡的getString和存儲 所謂返回 的getString的價值 變量 - 這就是所謂的 S型string--我們已經寫 這行代碼在那裡上面。 而且它是只有當我看到我的 在這裡手寫放大 我意識到多麼惡劣,這是。 但是,讓我們假設, 在右手側 是,但是,合理的 一個什麼樣的描述 一直在進行這一切 時間的getString。 的getString,當然,得到​​的字符串。 但是,這究竟意味著什麼? 這意味著它得到了一大塊 來自操作系統的內存 通過調用一個函數,稱為malloc的。 但後​​來更多。 然後填充 該內存塊 以字母的用戶具有 當然鍵入,緊接著,, 一個空字符或反斜杠 零在最後。 同時,在左手側 這個故事,這一切的時候, 我們已經聲明了一個變量,如第 而這個變量就是現在 將開始調用的指針。 這不是這裡面一箱 我們把串,Daven,本身 而是我們把在這方 箱體左側究竟是什麼? 是嗎? 聽眾:的地址 它位於內存中。 戴維·J·馬蘭:沒錯。 Daven的所在地址 位於存儲器。 不,所有Daven的所在, 本身,而是專門的地址 什麼? 是嗎? 聽眾:第一個字符。 戴維·J·馬蘭:第一個字符 在Daven,其中,在這種情況下, 我提出了任意 和不切實際1,OX1, 它的意思是, 1的十六進制數。 但是,它可能會 是一個更大的數字 我們可能會得出 以0X作為前綴, 代表一個十六進制字符。 而且,由於我們並不需要知道在哪裡 Daven的字符的其餘部分 是因為,有什麼簡單的設計 決定這是多年前? 是嗎? 聽眾:反斜杠0。 戴維·J·馬蘭:是的,沒錯。 反斜線0可以讓你,儘管在 線性時間,來遍歷字符串 由左到右行走, 用for循環,或同時 環或類似的東西 這一點,決定了哦,這裡 是這個特定字符串的結尾。 所以只用在地址 字符串的開始, 我們可以訪問的全部 它,因為這一切的同時, 一個字符串,剛剛一個char明星。 因此,這的確精緻繼續使用 在CS50庫,而且這樣的抽象, 可以這麼說,但我們會 首先,看看到底 什麼是怎麼回事 下面這整個時間。 所以,你可能還記得這個例子中, 同樣,從去年的時候,比較0, 這實際上並沒有進行比較。 但是,我們開始解決這個問題。 但是作為也許是複習, 我可能感興趣的人 粉紅色的大象的今天, 還長呢? 怎麼樣,你在前面? [聽不清]。 上來吧。 並且在此期間, 你上來,讓我們 考慮了一會兒就好了什麼 這段代碼實際上做的事情。 它聲明兩個變量了 頂,S和T,並調用的getString。 這不是一個非常用戶友好的程序, 因為它不會告訴你的事。 但是,讓我們姑且我們 重點是多汁的一部分。 然後我們做的,如果s等於 等於T,應該說printf的, 您鍵入同樣的事情。 你好。 你叫什麼名字? 詹妮爾:詹妮爾。 戴維·J·馬蘭:詹妮爾, 很高興認識你。 所以,你在挑戰 手這頭大象 是第一個吸引我們的是什麼圖片 被代表的前兩個 線。 因此,S和T可能是 顯示在畫面上如何? 而且你可以繪製與 將手指放在這個大屏幕上。 因此,有兩部分,以 該方程的每一側。 所以有S上的左側,並且 然後GetString的右邊。 再有就是噸左邊, 然後GetString的右邊。 那麼我們如何開始 繪製的畫面, 表示這是怎麼回事 這裡的記憶,你會說什麼? 讓我讓你解釋 你在做什麼,當您去。 詹妮爾:好的。 嗯,首先,它會問 你得到輸入字符串。 它會store--哦,對不起。 戴維·J·馬蘭:確定。 好。 而這個叫什麼? 哦,好吧。 繼續前進。 我不是故意要打斷。 詹妮爾:對不起。 因此,將其輸入到 地址of--不能確定。 我不記得確切的數字, 但我相信這是從0開始。 戴維·J·馬蘭:沒關係, 因為我做的數字了, 所以沒有正確的答案。 詹妮爾:用0起弧。 戴維·J·馬蘭:好了,元素0。 當然。 詹妮爾:然後如果是 像剛才兩個letter-- 戴維·J·馬蘭:好了,還給你。 詹妮爾:所以元素0, 然後元件1或元件2。 戴維·J·馬蘭:而且這一塊 圖片是你畫的權利嗎? 給GetString的調用? 或s的聲明? 詹妮爾:報關 的S,我相信。 哦,對的getString,因為它會 被輸入到每一個[?區。 ?] 戴維·J·馬蘭:好。 沒錯。 儘管這有效地 返回一個數組,調用, 當我們回到一個字符串,我們可以 索引使用01和2的字符串。 從技術上講,這很可能是 個別地址表示, 但是這很好。 於是想,如果我可以快 轉發給我們留下了 最後時刻,如果一個 字符串是克A B E, 反斜杠0,從而表示Gabe的 輸入,怎麼可能,我們代表就談到? 如果是這樣的存儲器那 被送回了的getString? 詹妮爾:這將是 由電弧所表示? 戴維·J·馬蘭:通過電弧? 哦,不。 遠的不說,形象地, 讓我繼續前進 和建議,如果這是秒,這 是的getString的返回值。 而你畫這是0,1,2,其中 是完全合理的,因為我們 可以索引到字符串,作為這樣。 但剛需一致 最後一次,讓我先走 並隨意提出這 是地址1,這是地址2, 這是地址3,依此類推。 因此,剛需超 顯然,這是怎麼回事 s中去,作為一個結果, 代碼的第一行,你會說什麼? 詹妮爾:地址1? 戴維·J·馬蘭:沒錯。 因此,解決為0x1。 而與此同時,讓我繼續前進, 重複的很多東西,你做 在這裡添加自己噸。 如果我要在加布型 再一次,第二次, 當用的getString提示,其中, 當然,被加布要去? 那麼,presumably-- 詹妮爾:像在這裡? 戴維·J·馬蘭:是的。 詹妮爾:或者它也是在同一個箱子? 戴維·J·馬蘭:我建議,是啊, 準確,因此,在這些附加的盒子。 但是,什麼是現在的關鍵是,即使 雖然我畫這些八九不離十 together--為0x1,這 被0x2--在現實中, 這個現在可能是地址為0x10, 例如,和為0x11,以及0x12的 等等。 因此,如果是這樣的話, 這是怎麼回事結束了在這裡噸? 詹妮爾:為0x10? 戴維·J·馬蘭:沒錯。 因此,為0x10。 所以現在,最後一個問題。 你有,到目前為止,已經工作了 最難的大象迄今。 事到如今,如果我拉起碼 再次,當我這樣做,在三線, 如果s等於等於T,我算什麼實際 相比較,我們在這裡畫? 詹妮爾:這兩個地址? 戴維·J·馬蘭:沒錯。 所以,我要說的是S等於等於t? 換句話說,是1等於等於10? 並且,當然,在 答案很明顯,現在是,沒有。 所以這個方案最終是 要打印的內容,你會說什麼? 詹妮爾:它會是這樣, 您鍵入同樣的事情? 戴維·J·馬蘭:所以,如果 s是1和t是10? 詹妮爾:輸入不同的事情。 戴維·J·馬蘭:沒錯。 你輸入不同的事情。 好吧。 所以,掌聲雷動, 如果我們能在這裡。 [掌聲] 這是痛苦的。 我知道。 很好地完成。 所以,現在讓我們來看看,如果我們不能 梳理出什麼樣的修復程序。 當然,當我們固定this-- 現在我將代表green-- 我們做了幾個增強功能在這裡。 首先,正如一個理智 檢查一下,我先檢查 如果s等於null和T等於null。 而只是要清楚,如果可能 s或t為null,在這樣的代碼? 當可能s或t為null。 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 如果字符串用戶 鍵入的是太長時間 要裝入內存,或者一些 奇怪的角落情況下那樣, GetString的,正如我們所看到的,從字面上 今天,它的文檔中, 表示將返回null作為 一個特殊的標記值, 或者只是有點特殊符號 這意味著出事了。 因此,我們要檢查 是,因為事實證明 那空是一個非常危險的價值。 通常情況下,如果你嘗試做一些與 空涉及函數 - 它傳遞 作為輸入,對instance--該功能 很可能會崩潰,並用它, 記下你的整個程序。 因此,這第三條線,現在僅僅是一個理智 檢查,檢查錯誤,如果你願意。 這是一個好習慣,現在的 我們進入任何時候我們 嘗試使用一個值, 可能,可能,是空的。 現在,在第四行此處, “如果STRCMP(S,T),”好了, 那是什麼指? 好吧,我們說這是一個非常簡潔 命名函數的字符串比較。 及其在生命的目的是比較 其反對的第一個參數第二, 但不是在它們的地址而言, 因為我們沒有無意中片刻 以前的紅色代碼,但 而比較這兩個 在力所能及直觀的字符串 通過比較這一點,對這種方式, 針對這一點,針對這一點,並 然後停止,如果和當一個 還是我的兩個手指 打一個反斜杠0。 因此,有人年前實施的strcmp 實現我們的功能 我們希望我們會得到 僅通過比較兩個簡單的值。 現在,坦率地說,我把圖紙 所有這些不同的數字。 但現實是,我已經 製備這些向上的全部時間。 因此,讓我乾脆去 而這些亂塗出來 做一個點,在結束 這一天,並向前走, 我們不是真的要關心 有什麼解決的事情,其實 在存儲器中。 所以,我不會畫這些 種數的那麼多了, 我只是一個抽象的這個客場 小只箭更友好。 換言之,如果s是一個指針, 好了,讓我們只繪製它,從字面上看, 作為一個指針箭頭指向 從自身到別的東西, 而不用太擔心更多 這些地址的細節 其中,再次,我反正做了。 但是,我們可以看到這些地址, 有時,調試代碼的時候。 現在,同時,該計劃 當然,在這裡的修復, 通過比較該問題 這兩個字符串。 但是,我們遇到了另一個問題。 這是從複製 節目最後一次, 因此,我試圖利用 在一個字符串僅僅是第一個字符。 但究竟是什麼症狀 我們看到最後的時候 用戶鍵入一個值,如 加布於小寫的S, 那麼我們分配s轉換T, 如第三行那裡, 然後我試圖 資本噸支架0? 什麼效果 改變噸支架0嗎? 聽眾:它改變了第 戴維·J·馬蘭:是啊, 我換了S,以及。 因為什麼怎麼回事? 好吧,讓我看看,如果我能清潔 這幅畫,如下所示。 如果S是再次,字克, A,B,E,反斜杠,0和s 我們將繼續繪製一個框 在這裡,但沒有更多的地址。 讓我們停止做的事情了。 讓我們只畫一幅畫 簡化了世界。 當我宣布噸,串T, 創建的內存塊。 方碰巧是32 位在大多數計算機上。 事實上,如果你曾經聽說過的 具有32位體系結構的計算機, 真正看中的,說話,只是 意味著它採用32位地址。 而作為一個技術不談, 如果你曾經想知道 為什麼舊的電腦,如果你真的 想喝湯起來,有很多的RAM, 只能有一個最大 四個千兆字節的RAM, 好,這是因為,從字面上看, 您的舊電腦只能 計高達4 十億,4個十億字節, 因為它是使用32位 號碼的地址。 但在任何情況下,在該 比如,故事中的要簡單得多。 t是只是一個指針,或 真是一個char星,又名字符串。 怎麼辦我想更新這幅畫 現在的代碼,第二行, 點後,點,點? 當我做串T等於Š分號, 請問這張照片改變? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:是的。 沒錯。 我只是把一個箭頭從 噸方塊以相同的地址, 在相同的第一個字母給了。 或在技術上,如果這 男人仍然在為0x1, 這是因為雖然我有 這裡為0x1和0x1這裡。 但同樣,誰在乎 關於地址? 只是,現在最重要的想法。 因此,這是這裡發生了什麼。 所以,當然,如果你做T支架 0,這是數組符號, 的course--坦率地說,它看起來 像有一個數組在這裡, 但現在有這樣奇怪的事情。 要知道,編程語言, C,為您提供此功能, 由此,即使t是 指針,或s是一個指針, 您還可以使用熟悉的, 舒適的括號 符號去的第一要素, 或所述第二元件,或任何元件 在該指針指向 到,因為,據推測,它 是,因為在這種情況下, 指著一些數組。 那麼,我們如何解決這個問題? 坦率地說,這是它得到了 有點麻煩第一眼。 但這裡是一個新的和改進的版本。 因此,首先,我越來越 擺脫CS50庫, 只是揭露S是真的 一個char明星,只是一個代名詞。 和T也是一個char明星。 但對到底是怎麼回事 該行的右手側 其中T是賦值? 什麼是malloc的? 什麼是strlen的? 什麼是的sizeof(char)的? 為什麼非得這樣做 線看起來那麼複雜嗎? 它是什麼做在一個較高的水平? 什麼是存儲在T? 是嗎? 聽眾:它的分配 一定量的存儲空間。 它的存儲,我想, 信[聽不清]。 戴維·J·馬蘭:完美。 完美的。 它分配一個特定的 存儲空間量 存儲,據推測,未來的信件。 並且特別地,malloc的 因此,返回什麼? 聽眾:返回的[聽不清]? 戴維·J·馬蘭:沒錯。 返回的內存地址, 這只不過是一個奇特的方式, 返回的地址 該內存的第一個字節。 的責任是我記住 實際上有多少內存I 分配或要求的malloc的。 現在是多少呢? 好吧,即使有 很多括號在這裡, malloc的只需要一個參數。 和我指定的字符strlen,所以給 我盡可能多的字節,因為在S, 但新增一個。 為什麼呢? 是嗎? 聽眾:反斜杠0。 戴維·J·馬蘭:沒錯。 我們必須做一點家務。 所以,因為有一個反斜杠 0,我們最好記住這一點。 否則,我們將 創建一個字符串, 沒有特別的終結者。 同時,剛需超 肛門,我的sizeof(char)的, 萬一有人跑我 不上CS50設備代碼, 但也許在不同的計算機 乾脆在那裡字符 是一個字節,按照慣例,但有兩個 字節或更大的東西不止這些。 這是剛需超, 超級反感的錯誤。 儘管,在現實中,這是 最有可能將是一個1。 現在,同時,我繼續和複製 字符串,T支架i等於噸支架第 我將按照上週的 源代碼,看看是怎麼回事。 但關鍵的外賣,以及 我之所以把代碼現在綠, 是因為很最後一行 噸支架0等於TOUPPER, 具有的效果 轉增股本的字符串? T和/或S? 最後一行代碼。 只是T,是因為什麼 最少此時, 如果我稍微撤消最後一步, 什麼情況是,當我調用malloc, í基本上得到一個內存塊 這是相同的尺寸,原來, 因為這是算術我做到了。 我存儲在T地址 的內存塊。 儘管這看起來不錯 漂亮,漂亮,一片空白, 實際情況是有,我們會 保持通話,在這裡的垃圾值。 該內存塊可能很 也有之前被使用, 幾秒鐘,幾分鐘前。 因此,有可能完全是數字 或字母那裡,只是偶然。 但他們不是有效的,直到我 我自己填充此塊內存 與實際的字符,如我 做在for循環出現。 好吧? 所以,現在的高潮 這三個例子 那名看似打破最後一次, 這個互換的例子,這個功能 在這個意義上製作 它交換a和b。 但它並沒有什麼其他意義的工作? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 如果我要調用這個函數 從another--例如 從主一樣,在功能 我有一個變量,x和y,當我 上星期,同樣的代碼, 而我通過在X和Y 以交換,然後調用Swap--這一點, 當然是正確的版本 就是我們即將 see--沒有奏效。 那麼,什麼是定位? 好了,所以才要 顯然,讓我先走 還有 - 給我1秒在這裡,看 如果我能告訴你的最後一個,這 將in--讓我們來看看,如果我能找到 這種真正的fast--確定,[聽不清]。 好了,它就在那裡。 所以忽略我只是鍵入命令。 我希望它在檢索 最後一分鐘的一例 從去年的時間,這 現在所謂的無交換。 因此,沒有交換的地方 我們離開的最後一次, 因此,我初始化 X要1和y 2。 後來我打電話交換,傳遞1和2。 然後這個函數 在某種意義上工作, 但它沒有永久的 在x和y的影響。 因此,目前的問題是,怎麼現在 我們其實解決這個問題? 如何解決在眼前? 那麼,在swap.c,今天是新的, 看到一對夫婦的差異。 x和y是相同的。 但顯然 約25行有什麼不同? 最新消息那裡,如果你還記得 它看起來像一秒鐘前? 聽眾:[聽不清]。 戴維·J·馬蘭:是的。 所以連字號是一個新的作品 語法不僅這個程序中, 而且更普遍的CS50。 到目前為止,我不認為 我們見過的任何實例 還是真的在任何談論他們 細節,不是,也許,搶先其他 在節中,像這樣的符號。 嗯,原來符號是 最後張新語法 我們要學習的。 它的意思是在 一些變量的地址。 請問您的地址並點¯x住在哪裡? 但ÿ住什麼地址? 因為如果 之前根本問題 在x和y分別被傳遞 作為副本,我們真正想做的事 是提供交換與像寶貝一樣 地圖,導致其中x和y實際上 在RAM中,從而使 交換可以按照該圖 和去哪裡x或y標誌的地方 和改變實際值1和2 那裡。 所以交換需要稍微改變了。 乍看之下,這可能 似乎有點類似於字符的明星。 的確是。 所以a是一個指向什麼類型的數據, 在此基礎上突出部分? 所以這是一個int。 所以不再是一個int, 這是一個int的地址。 同樣,B現在準備 是一個int的地址。 所以,當我現在請交換從主, 我不會給交換1和2。 我要去給它像 牛的東西,黃牛的東西, 兩個地址,這將導致 交換自己的實際位置 在我的電腦的內存中。 所以,現在,我剩下的落實 需要改變一點點。 有什麼明顯的不同,現在 在這三行代碼? 有這些該死的明星都 過的地方,好嗎? 所以,這是怎麼回事嗎? 是嗎? 聽眾:這是很明顯[聽不清]。 戴維·J·馬蘭:沒錯。 所以在此context--,這是不 最好的設計決定,無可否認, 幾年前。 在這種情況下,其中 你只需要一個明星, 而你沒有的數據類型, 如int,立即到左邊, 而不是你有一個等號,顯然, 在這種情況下,當你說星A, 這意味著去 地址是在一個。 按照藏寶圖,可以這麼說。 並且同時,在第37行, 這意味著同樣的事情。 去的地址,並把什麼呢? 不管是在 地理位置使得b指定。 換句話說,去到b。 獲得該值。 去和每平等 簽署,賦值運算符, 把該值存在。 同樣,INT溫度僅僅是一個int。 沒有什麼需要改一下溫度。 這只是一個備用的玻璃從安嫩伯格 對於一些牛奶或橙汁。 但我需要說的,去到B。 去那個目的地, 放在那裡的溫度值。 因此,發生了什麼呢? 當我真正稱之為交換這個時候,如果 這第一盤在這裡代表主, 當第二盤代表交換, 我通過符號x和符號ÿ 從主來交換,只是要清楚, 這是什麼堆棧幀接收? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 x的地址和y的地址。 而你能想到的這些 如郵寄地址。 33牛津街和35 牛津街和你 要移動的兩棟樓 這是在這些地方。 這有點荒謬的想法, 但是這就是我們所說的地址。 凡在世界上可以 你會發現這兩個整數? 凡在世界上你 找到這兩個建築物? 因此,如果最後,畢竟這個時候我 進入今天的源代碼和編譯 交換和運行./swap,最後,為 第一次,我們確實看到, 我的價值觀的確有 已成功交換。 而現在,我們甚至可以把 請注意這一點,比如,廣發銀行。 所以,讓我去到同一個文件中。 讓我繼續運行./swap的GDB。 而現在,在交換,我會去 未來,並設置一個斷點在主。 現在我要去 繼續運行該程序。 現在我們看到我的代碼 停在該行。 如果我繼續和打印 X,我應該在這裡看到的? 這是一個問題。 再說一遍? 聽眾:[聽不清]。 戴維·J·馬蘭:所以 隨機數,也許。 也許我很幸運,它的 優雅而簡單,如0。 但也許這是一些隨機數。 在這種情況下,我真的很幸運。 這恰好是0。 但它確實是運氣, 因為直到我 輸入下一個,然後打印x的那 代碼行,19行,被執行死刑。 同時,如果我輸入下一一遍, 現在打印出Y,我要見2。 現在,如果我輸入下一個,它要 變得有點混亂,因為現在, 中的printf會出現在 在屏幕上,因為它沒有。 x是1。 讓我們再次做到這一點。 而現在,這裡的地方 事情變得有趣。 在我打電話交換,甚至一步 進去,讓我們一點點偷看。 x是,再次,1。 Y是當然,快清醒 檢查,2,所以並不難有。 但是,什麼是符號X你是否 答案,它是一種時髦好看。 但INT明星在括號只是 對這種說法GDP的方式是一個地址。 它不是一個整數,它是一個指向 int或以其他方式被稱為一個地址。 這是什麼瘋狂的事? 我們從來沒有見過的東西 很喜歡之前。 因此,這是在我的電腦的地址 內存,其中x恰好住。 這是黃牛的東西。 這是坦率地說,為什麼 我開始畫箭頭, 不是數字的, 因為誰真正關心 您的int是在一個特定的 地址是那麼大。 但bffff0c4,這些都是 的確十六進制數字, 這是0到f。 因此,我們不會過多糾纏 長在什麼地方的東西。 但是,如果我打印出Y, 當然,我看到2。 但符號Y,我看這個地址。 並請注意,為好奇, 相距多遠是x和y? 您可以忽略大部分的地址。 四個字節。 而這與我們的一致 早前聲稱有多大是一個int? 四個字節。 所以看起來一切都排隊 很好,你可能希望,在內存中。 所以,現在,讓我們快進 這個故事的結尾。 讓我們繼續前進,步型, 潛入交換功能。 現在發現,如果我輸入一個,它的 相同,x的地址。 如果我B型是相同的 到y的地址。 所以,我應該怎樣,如果我看到 說,進入地址的? 因此,打印星號標示。 所以,明星意味著去那裡,在這種情況下。 &符號意味著什麼的地址。 所以,明星的手段1。 並打印星級的住宿給我2。 讓我假設,就目前而言, 至少所述代碼 現在進入執行即可 通過這種方式的理由。 但我們會在不久重新討論這個想法。 所以這個版本的互換 現在是正確的,並且允許 我們來交換該特定數據類型。 所以任何疑問然後交換? 在星? 對地址? 你會看到,有 問題集4,排序, 但問題集5,絕對,如何將這些 東西是有用的,並得到更多的 熟悉他們,作為一個結果。 什麼呢? 好吧。 所以malloc的是,再次,此功能 剛剛分配內存,內存 分配。 以及為什麼是這樣有用嗎? 那麼,這一切的時候, 你一直在使用malloc。 如果你現在怎麼考慮的 GetString的作品,據推測,這是 被問的人一大塊 記憶,隨時在用戶鍵入字符串 在,因為我們肯定 不知道,因為CS50的工作人員, 有多大的字符串,人類 要鍵入可能。 因此,讓我們,第一次,開始 剝開如何CS50庫工程, 通過幾個實例來 這將導致我們的。 所以,如果我打開gedit的 開拓scanf函數0, 我們將看到下面的代碼。 scanf函數0,可以在網站上 今天,有代碼相對較少的行 在這裡,14至20。 讓我們來看看它在做什麼。 它聲明為int,名為x。 它說像,數請。 而現在它說,scanf函數%I,&X。 因此,有一堆新的東西出現。 但是scanf函數,你可以種思考 作為printf的相反。 printf的,當然,打印到屏幕上。 scanf的排序從用戶的掃描 鍵盤的東西,他或她已經打出來。 %i是一樣的printf。 這意味著預期 用戶鍵入一個int。 而現在,你為什麼認為我 可能是通過scanf函數&X? 如果目的在scanf生活 是得到的東西從用戶 是什麼意思 通過它,與X,現在呢? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 無論我,人,請在我的輸入 將被保存在該位置。 這是不夠的,還記得,剛 通過在X,因為我們已經看到, 任何時候,你只需通過一個原始變量, 就像一個int,一些其他的功能, 當然,它可以改變 可變的,但不會永久。 它不能對主要的效果。 它只能改變自己的本地副本。 但相反,如果你不這樣做 給我實際的詮釋, 但你給我方向 在INT,我現在,是scanf函數, 當然,我可以按照這 解決並把一些有 所以你可以訪問它。 所以,當我運行這個程序,讓我們來看看。 使scanf函數0點斜線,scanf函數0。 如果我現在鍵入數字 像50,感謝50。 如果我現在鍵入數字一樣 負1,為負1。 我現在鍵入數字如1.5,HM。 為什麼我的程序不理我了? 嗯,因為簡單地說,我告訴 只期待一個int。 好吧。 所以這是其中的一個版本。 讓我們拿東西了一個缺口, 提出,這是不好的。 而就在這裡一個很簡單的例子, 怎麼我們就可以開始編寫代碼 其他人可以利用或 做不好的事情妥協。 所以第16行,如此相似 在精神之前, 但我不會宣布它詮釋這個時候。 我宣布它炭星,又名字符串。 但是,這究竟意味著什麼? 所以,如果我不指定address--和 我打電話是隨意,緩衝, 但我可以把它稱為為s,是simple-- 然後我做到這一點,給我解釋一下, 如果可以的話,基於先前 邏輯是什麼scanf函數在做線18, 如果傳%s和緩衝區, 這是一個地址? 什麼是scanf函數,如果你申請的 完全相同的邏輯版本0, 當將試圖在這裡做, 在用戶類型的東西嗎? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 scanf函數,通過邏輯較早, 將要採取的串 該人的類型化 in--它現在是一個字符串, 它不是一個數,據推測, 如果他或她cooperates-- 並且它會試圖把那 字符串在內存中的任何地址 緩衝區指定。 這是偉大的,因為緩衝 的確意味著是一個地址。 但我要求這個節目是越野車的 很嚴肅的方式,因為價值是什麼 默認情況下緩衝區? 我有什麼初始化為? 什麼的內存塊? 我沒有,對不對? 所以,即使我已經分配了 焦恆星的不再叫S, 它不是所謂的,buffer--所以 讓我們來繪製變量名 現在的buffer--如果我沒有 所謂的getString或malloc的位置, 這實際上意味著, 緩衝區只是一些垃圾值。 現在是什麼意思? 這意味著,我已經告訴scanf函數 期望從用戶的字符串。 而且你知道嗎? 不管這件事情是指向 to--和我畫問號, 但在現實中,這將是 像OX1,2,3,對不對? 這是一些虛假的價值,僅僅 恰好從之前在那裡。 所以,換句話說,它是 彷彿緩衝只是 指著東西在內存中。 我不知道是什麼。 所以,如果我輸入加布現在,這是怎麼回事 嘗試把G-A-B-E / 0出現。 但誰知道這是什麼嗎? 和過去一樣,任何 我們試圖去觸摸時間 不屬於存儲器 對我們來說,發生了什麼事? 或幾乎所有的時間。 分段錯誤,對吧? 這個箭頭,我不知道它是 指點。它只是一些隨機值。 當然,如果你解釋 一個隨機值作為地址, 你會去 一些隨機的目的地。 所以加布可能確實崩潰 我在這裡這種情況下程序。 所以,我們可以做到這一點幾乎是壞? 考慮這個第三和 scanf函數的最後一個例子。 這個版本是在何種意義上比較好? 如果你是舒服了 以前的問題,這是更好的。 為什麼呢? 聽眾:[聽不清]。 戴維·J·馬蘭:好。 線16,以便該情況下 較好,在這個意義上 我們是明確的 分配一些內存。 我們不使用malloc, 我們使用了2週 只是聲明數組的方法。 而我們在此之前一個字符串說過 是一個字符只是一個數組, 所以這是完全合法的。 但它的,當然,如 您注意,固定的大小,16。 因此,這個計劃是 完全安全的,如果我輸入 在一個文字串,兩個字符的 串,15字符的字符串。 但是當我開始打字16, 17,第18,千字符串, 這裡是該字符串將要結束? 這將結束部分在這裡。 但誰知道還有什麼 超出了界限 這個陣列呢? 這是因為雖然我 在這裡宣布16箱。 因此,而不是畫出來的所有16中,我們將 只是假裝我畫16。 但是,如果我再嘗試讀取字符串 這是更長的時間,如50個字符, 我要開始把 A,B,C,D,X,Y,Z。 這大概是 其它一些內存段 即,再次,可能會導致 我的程序崩潰, 因為我沒有要求 事情不止16個字節。 那麼,誰在乎呢? 好了,這裡的CS50庫。 而且大部分這只是 類似的指令往上頂。 該CS50庫,這一切的時候, 已經有這一行52行。 我們已經看到的typedef,或 你會看到的typedef 在PSET 4,剛剛創建了一個 同義詞其中焦炭明星可以更 簡稱為字符串。 因此,這是一個 數輪培訓 我們已經偷偷使用了引擎蓋下方。 同時,這裡的函數,getchar函數。 現在很明顯,沒有身體吧。 而事實上,如果我繼續 滾動,我實際上並不 看不到任何的實現 這些功能。 作為一個全面的檢查,這是為什麼? 聽眾:[聽不清]。 戴維·J·馬蘭:是的。 因此,這是頭文件。 和頭文件包含原型, 再加上一些其他的東西,現在看來, 喜歡的類型定義。 但在CS50.c,我們已經 從來沒有給你顧左右而言他, 但一直在CS50所有家電 這個時候,內心深處的文件夾, 注意到有一個整體 在這裡一堆功能。 事實上,我們向下滾動。 讓我們忽略了他們中的大多數現在。 但是,向下滾動到調用getInt 看看調用getInt是如何工作的。 因此,這裡是調用getInt。 如果你真的關心如何獲得 INT作品,這裡是它的文檔。 而當中的事 它說的是它告訴你 什麼值的範圍就可以返回。 它本質上是負面的2十億 以正面的2十億,給予或採取。 而事實證明,這一切 時間,即使我們從來沒有 有了你檢查它, 如果出現錯誤, 事實證明,所有的 此時,調用getInt有 已返回一個特殊的 常量,不為空, 而是INT_MAX,這是 只是一個程序員的約定。 這意味著這裡是一個特殊的值。 請一定要檢查這一點,只是 在出錯的時候。 但是,我們從來沒有困擾 同的是,到目前為止, 因為再次,這 是為了簡化。 但如何調用getInt得到實施? 嗯,一,它不帶任何參數。 我們知道這一點。 它返回一個int。 我們知道這一點。 那麼它是怎樣的引擎蓋底下工作? 所以這是很明顯的無限 環,其中一個至少外觀。 請注意,我們使用的getString。 所以這很有趣。調用getInt 調用我們自己的函數,的getString。 現在為什麼會變成這樣? 為什麼我會被防守 在這裡行165? 哪些本著可能發生 164,只是要清楚嗎? 這是同樣的答案和以前一樣。 可能僅僅是內存不足。 不順心的事了的getString, 我們必須能夠處理的。 而我之所以不返回null是 即,在技術上,空是一個指針。 調用getInt必須返回一個int。 所以我隨意 決定,從本質上講, 有2十億,而奮鬥,是怎麼回事 是一種特殊的價值,我永遠不可能 其實獲取用戶。 這只是一個價值我要去 浪費,代表一個錯誤代碼。 所以,現在,事情變得有點奇特。 它不是完全一樣的功能 和以前一樣,但它是非常相似的。 所以請注意,我在這裡聲明,符合 172,無論是一個int n和一個char℃。 然後我用這個時髦的路線, sscanf的,它原來 不掃描從鍵盤輸入的字符串。 它代表著現有的字符串 用戶已經鍵入英寸 所以,我已經叫的getString,這 意味著我有一個字符串在內存中。 sscanf的是什麼,你會 調用解析函數。 它著眼於我有串 鍵入,字符一個字符, 並做一些有用的東西。 該字符串被存儲在一行。 我知道,只有通過去 備份在這裡,說,哦,好吧, 我把它叫做不發這個時間,但行。 而現在,這是一個有點不同。 但是這實際上意味著,其原因 我們會有點潮手在今天, 我們正在檢查 查看該用戶鍵入 與詮釋,也許另一個字符。 如果用戶輸入了一個int,它的 將要被存儲在正,因為我 按地址傳遞這一點, 今天我們看到的新把戲。 如果用戶還輸入 像123x,使得x 將要結束了 字母字符c。 現在事實證明,sscanf的 告訴我,智能化, 多少個變量是sscanf的 能夠成功地填補。 所以通過這種邏輯,如果該函數 我實施的調用getInt, 但我檢查, 潛在地,對於用戶 已經輸入了一個int 其次是別的東西, 什麼才是我想要的sscanf的 返回值真的是? 如果目的是要獲得 只是從用戶的詮釋? 所以,如果sscanf的回報 2,是什麼意思呢? 用戶鍵入 是這樣,從字面上看, 123x,這只是無稽之談。 這是一個錯誤,並 我要檢查的。 因此,如果這在用戶的類型,由 這個邏輯有哪些呢sscanf的回報, 你會說什麼? 所以它會返回2,因為 123是要去這裡, 而X是要結束在這裡。 但我不想在x得到填補。 我想,sscanf會只成功 灌裝頭的變量。 所以這就是為什麼我 想sscanf會返回1。 如果這是有點在頭上 就目前而言,這是完全正常。 意識到雖然,其中一個 調用getInt和GetString值 就是我們正在做的啦! 很多錯誤檢查這樣使 是,到今天為止,你幾乎可以 在你的鍵盤輸入任何東西, 我們會抓住它。 我們肯定的是, 工作人員,肯定不會 在一個錯誤的來源你 計劃,因為我們的防守 檢查所有的愚蠢的 的東西,用戶可能會做, 如輸入一個字符串,當 你真的想要詮釋。 因此,對於now--我們就來 回此之前long-- 但是這一切的時候, 的getString和調用getInt有 在使用這種發動機罩下方 內存地址的基本思路。 所以,現在,讓我們把事情 對用戶來說更加友好。 您可能還記得,從去年賓基 時間 - 如果我的鼠標會cooperate--所以 我們有這個代碼,這 坦率地說,是相當荒謬的。 此代碼實現了什麼 有用的,但它是例子 該教授Parlante 為了表示用於 什麼樣的是怎麼回事 項目涉及內存。 因此,讓我們複述這 故事超簡要介紹。 這些前兩行,在 英語,做什麼,會說什麼? 就在合理的人,但 稍微專業術語,取刺。 聽眾:[聽不清]。 戴維·J·馬蘭:好,你確定 地址為你的x和y變量。 不大,因為x和y是未 變量在傳統意義上的。 x和y是地址 或者將存儲地址。 因此,讓我們試試這個一次。 不是一個糟糕的開局,但。 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:好。 我認為這是一個小清潔。 聲明兩個三分球,兩個整數。 而我們稱他們為x和y。 或者,如果我們畫 此為圖片,再 記得很簡單,所有 我們正在做的與第一線 正在制定一個盒子這樣的, 在它的一些垃圾的價值, 並調用它的X,然後 另一個盒子這樣的, 與一些垃圾值 它,叫它年。 我們已經聲明了兩個 三分球,最終 將存儲一個int的地址。 所以這一切都在那裡。 所以當賓基這樣做,則 粘土只是看著這樣的。 和尼克剛種 包裹起來的箭, 彷彿他們不是指向任何地方 特別是,因為他們只是 垃圾值。 他們沒有明確的初始化 任何地方尤其如此。 現在的下一行 代碼,召回,是這樣的。 因此,在合理的人性化, 但有些技術英語, 什麼是這行代碼在做什麼? 是嗎? 聽眾:[聽不清]。 戴維·J·馬蘭:完美。 它分配的大塊 內存是一個int的大小。 而這一半的答案。 你回答正確 一半的表情。 什麼是發生在 等號左邊? 是嗎? 聽眾:和受讓人 它給變量x? 戴維·J·馬蘭:和受讓人 它給變量x。 總括來說,右側會分配 足夠的內存來存儲一個int。 但具體的malloc 返回地址 這大塊的內存,您已中 只是建議被存放在X。 那麼,尼克做了最後一次帶賓基是 他拖著那指針移出,粘土, 現在指向一個內存塊白 等於一個int的大小。 事實上,這意味著 來表示四個字節。 現在,代碼的下一行 這樣做,星x被42。 所以42是簡單的 右手側,生活的含義。 左側,星x表示什麼? 這也可能gone--沒關係。 行。 聽眾:基本上, 進入[聽不清] 戴維·J·馬蘭:好。 聽眾:[聽不清]。 戴維·J·馬蘭:沒錯。 左手邊是指去為x。 x是地址。 這就像33牛津街,或OX1。 和星x表示去那家 解決和放什麼呢? 42。 所以,事實上,這正是尼克做了。 他開始用, 本質上,精神上 用手指指著 的x,下面的箭頭 到右側的白框 側,並且把數42那裡。 但後​​來事情得到了 有點危險吧? 賓基的即將失去他的頭。 星y等於13,運氣不好,意味著什麼? 所以,明星y表示去的地址y中。 但是,什麼是Y中的地址? 好吧,這是垃圾的價值,對不對? 我畫它作為一個問號。 尼克畫了它作為一個蜷縮箭頭。 而且只要你嘗試 做明星Y,說去那裡, 但沒有一個合法的 地址,它的一些虛假的位置, 該計劃的要崩潰。 和賓基的頭部會 飛了出去,在這裡,因為它沒有。 所以,最後,這個方案 只是平了破綻。 這是一個錯誤的程序。 它需要加以固定。 而唯一的辦法,真的,要解決它 將是,舉例來說,這條線, 我們甚至沒有去,因為 程序崩潰得太快。 但是,如果我們要解決這個問題,有什麼 效果確實做Ÿ等於x具有? 那麼,它基本上是在點ÿ 任何值x指向。 因此,在尼克的故事, 或賓基的故事,無論是 x和y分別為指向 白色塊的存儲器, 這樣一來,最終,當 做明星Ÿ再次等於13, 你最終將在13 適當的位置。 因此,所有這些線路都完美 合法的,除了這一個, 之前,當它發生 實際分配Ÿ一定的價值。 現在值得慶幸的是,你不 要通過推理全部 這些類型的問題你自己。 讓我繼續前進,開 在這裡一個終端窗口 與開拓,就一下, 超級短節目的 也就是那種毫無意義的。 這是醜陋的。 它沒有實現任何用處。 但它確實證明問題 記憶,讓我們一起來看看。 主要的,超級簡單。 這顯然是調用一個函數, F,然後返回0。 這是一種很難搞砸。 所以,主要是相當不錯的,到目前為止。 所以f是有問題的。 只是沒放多少 努力為它命名 在這裡,以保持重心的代碼。 f有兩行。 讓我們看看現在怎麼回事。 這樣一方面 這裡 - 並讓我 與前此一致 example--一方面, 左手側是 做什麼,用英語? 它is-- 聽眾:創建一個指針。 戴維·J·馬蘭:創建一個指針 為int,把它x即可。 因此,它的創造者一個箱子 我一直畫在觸摸屏上。 現在,對右手 當然一面,malloc的, 被分配的內存塊。 而只是要清楚,怎麼 多少內存是它明顯 分配,如果你只是 種做數學題嗎? 因此,它是40個字節。 我知道,只是因為我知道的 整數,在CS50器具,至少 是四個字節。 所以,10次4 40。 所以這是存儲一個x,地址 第一次出40的整數 已分配的空間回來了, 背,背,背來。 而這正是重點對malloc的。 它並不需要一點點內存 在這裡,有一點在這裡,在這裡一點點。 它為您提供了一個內存塊, 連續地,從操作 系統。 現在來談談這個, 點¯x支架10等於0? 獨斷專行的代碼。 它沒有實現任何用處。 但有意思的是, 因為變量x支架10--? 是嗎? 聽眾:[聽不清]? 戴維·J·馬蘭:X支架 10不必是空的。 空的細節只有進場 用字符串,在字符串的結尾。 但一個好的想法。 有多大這個數組,甚至 雖然我已經分配40個字節? 這是從0到9,對不對? 這10個整數,總。 40個字節,但是10個整數, 索引0到0。 那麼,什麼是是X支架10? 它實際上是一些 未知的垃圾值。 這是一個不屬於我的記憶。 我不應該碰的 字節數41,42,43,44。 我會稍微有點遠。 事實上,如果我運行這個 程序時,它很可能會崩潰。 但有時,我們會得到幸運。 所以,只是為了演示 this--坦率地說, 你永遠不知道你之前 做它 - 讓我們來運行的。 它實際上並沒有崩潰。 但是,如果我改變這一狀況,為 例如,要像千, 使這真的 故意的,讓我們來看看 如果我們可以得到它的崩潰這個時候。 好吧,它沒有崩潰。 如何約10萬? 讓我們來改造它,現在重新運行它。 行。 唷。 好吧。 因此很明顯,同樣,這些 內存段,可以這麼說, 是相當大的,所以我們可以 一次又一次得到幸運。 但最終,一旦你得到可笑 真正炎等在屏幕上, 你觸摸記憶真的, 真的不屬於你。 但坦率地說,這些 種蟲子會 是難當 找出你自己的。 不過,值得慶幸的是,作為程序員,我們有 工具,使我們能夠做到這一點的我們。 因此,這是,也許是一 最醜的節目, 比gdb的輸出,甚至醜陋。 但它總有一條線或 2是超級有用。 Valgrind是一個程序,可以幫助 你沒有調試一個程序,本身 但是發現內存相關 的問題,特別是。 它會自動運行您的代碼 你看,至少兩件事情。 一,你做了什麼 偶然像觸摸記憶 那不屬於你? 這將幫助你找到這些情況。 其二,它會幫助 你發現了一種叫做 內存洩露,我們有 全然不顧,天真, 一段時間和幸福地。 但事實證明,所有的 此時,每當 你所謂的getString在 我們這麼多的節目, 你問工作 系統記憶體, 但你有什麼回憶 有史以來給它 回來了,做unalloc,或 免費的,因為它的調用。 沒有,因為我們從來沒有 要求你這樣做。 但所有這一次,程序 你一直在寫C語言 已經洩漏內存, 要求經營 系統越來越 存儲字符串和諸如此類的東西, 但從來沒有遞了回去。 而現在,這是一個有點 à簡單化的, 但如果你曾經運行在Mac或 你的電腦很長一段時間,開 大量的節目, 也許關閉程序, 而即使你的 電腦沒有死機, 它變得這麼慢得多, 好像真的 使用大量的內存或 資源,即使, 如果你不連 觸摸鍵盤, 可能be--但不always--能 是因為你正在運行的程序 有自己的內存洩漏。 他們不斷地問操作系統的更多, 更多的內存,但忘記了它, 實際上並不使用它,但 因此,服用內存離開 從可能希望它的其他程序。 所以這是一個常見的解釋。 現在,這裡的地方Valgrind的公司 輸出是完全 殘暴的那些少 更舒適的一致好評。 但有趣 東西是正確的在這裡。 它告訴我一個無效的寫 大小4發生這個程序中, 特別是,在memory.c的第21行。 如果我去到第21行,嗯,的確有 是大小為4的無效寫。 為什麼大小4? 那麼,這number--它 可能是anything--是一個int。 因此,這四個字節。 所以,我把四個字節 他們不屬於。 這就是Valgrind的 實際上是告訴我。 此外,它也將 告訴我,因為我們將看到, 當你運行這個在未來的PSET,如果和 當你的內存洩漏,這確實是 我有,因為我打過電話 malloc的,但我並沒有實際 叫,在這種情況下,自由 我們最終會看到 是的malloc相反。 所以,現在,我認為,最後一個例子。 所以這一塊是一個有點多 晦澀難懂,但它也許是 最大的原因 小心內存, 究其原因,很多節目 和/或Web服務器,甚至到今天, 被接管壞人的地方 在互聯網上誰是莫名其妙 發送偽造的數據包到服務器 試圖破壞您的賬戶, 或者把你的數據,或只是 一般拿過來一台機器。 緩衝區溢出,隨著 顧名思義,手段 不溢出為int,而是一個緩衝區。 和緩衝僅僅是一個奇特的方式 的說這是一串記憶。 事實上,我叫一個字符串 前緩衝區,而不​​是S,。 因為如果它是一個緩衝, 像在YouTube的意義, 或者您正在觀看的視頻的任何時間, 你可能已經看到這個詞的緩衝, 點,點,點。 這是令人難以置信的煩人。 而這僅僅意味著 您的視頻播放器 試圖下載大量 字節,大量的字節 從網上的視頻。 但它是緩慢的,所以它的嘗試 下載了一堆人 填充緩衝器,一個容器,從而使 你有足夠的字節,它可以再 告訴你的視頻, 不停頓不斷。 但事實證明,你可以 有一個緩衝,以這個大。 但盡量把這麼多數據 微博,很糟糕的事情可能發生。 因此,例如,讓我們來看看 一個例子的這個最終預告片。 這是另一種方案 即,乍一看, 什麼都不做超級有用。 它有一個主要功能 調用該函數f。 而且函數f,在這裡,有 一個char數組,稱為大小12℃,。 然後它用這個 新的函數調用strncpy()函數。 事實證明,這種簡單 代碼簡單的線條,只是兩條線, 我們已經做了我的整個程序, 因此,我的整個電腦, 我的用戶帳戶,我的硬盤 開車可能受到任何人 誰知道,是不夠好,運行 這個節目帶有一定的命令行 的說法。 換句話說,如果這個壞傢伙 通過鍵入把argvargv [1]內 在鍵盤非常特製 字符串,而不是ABC,123,但本質上, 代表可執行的二進制符號 代碼,一個程序,他或她寫道: 用這種簡單的方案,這是 代表的數以千計的節目 這同樣是脆弱的,敢說, 他或她可以最終刪除所有 在我的硬盤驅動器中的文件,得到了 閃爍提示,以便他或她可以 自己輸入命令, 電子郵件中的所有文件到自己。 什麼我可以做的,他 或她可以使用此代碼做。 我們不太解決這事。 而事實上,這將 涉及小圖片 這樣,我們將很快到來 理解就更好了。 但是今天,讓我們結束 什麼是有希望稍微 可以理解的XKCD笑話, 直到我們重新開始下一次。 好吧。 星期三見。 [音樂播放] 演講嘉賓:現在,深 思想,通過Daven法納姆。 記憶就像是跳進了一堆 金黃的樹葉在週日下午。 風拂過,你折騰 hair--哦,我懷念的日子when-- [笑]