字幕列表 影片播放 列印所有字幕 列印翻譯字幕 列印英文字幕 [MUSIC PLAYING] [音樂播放] >> DAVID J. MALAN: All right. >> 戴維·J·馬蘭:好吧。 This is CS50. 這是CS50。 And this is the start of week 5. 這是5週的開始。 And as you may have noticed, some of the material 正如你可能已經注意到, 一些材料 is getting a little more complex, the little denser. 越來越多一點 複雜,小更密。 >> And it's very easy, especially if you've been in the habit for some time, >> 而且它是很容易的,尤其是當 你已經在習慣了一段時間, to be trying to scribble down most anything we do, we're saying in class. 是為了要塗下最 什麼我們做什麼,我們說在課堂上。 But realize, that is not perhaps the ideal pedagogical approach 但要意識到,這也許不是 理想的教學方法 to learning this kind of material, and material more generally. 學習這種物質, 而材料更普遍。 And so we are pleased to announce that CS50's own Gheng 因此,我們很高興 宣布,CS50自己Gheng Gong has begun to prepare a canonical set of notes 龔已開始準備 一個規範的集合票據 for the course, the hope of which is that, one, these 用於操作過程中,希望 其是,一個,這些 not only serve as a reference and a resource 不僅作為 參考和資源 for reviewing material and going back through material that might have 審查材料中去 回通過材料可能具有的 escaped you the first time around, but also so that your heads can be more 逃脫你在第一時間左右,但 也讓你的頭可以更 up than down, when it comes time to lecture, 向上比下降,當它 談到時間來講課, so that you might engage more thoughtfully, as 所以,你可能搞 更周到,為 opposed to more scribbly. 相對於更雜亂。 >> With that said, what you'll find on the website is such documents as this. >> 雖這麼說,你會發現 該網站是這樣的文件,因為這。 And notice, at top left, there's not only a table of contents, 並請注意,在左上角,有 不僅表的內容, but also time codes that will immediately jump you 而且時間碼的 會立即跳到你 to the appropriate part in the video online. 到相應的部分 在視頻網上。 And what Chang here has done is, essentially, documented 什麼常在這裡做了 在本質上,記載 what happened in this particular lecture. 發生了什麼事在這 特別講座。 And many of the lectures are already online now with this URL. 和許多的講座是 已經在線使用這個網址。 And we'll continue to post the remainder of those by the end of this week, 我們將繼續張貼其餘 那些在本週末結束, so do take advantage of that resource. 所以不要採取資源優勢。 >> So without further ado, we started to peel back >> 因此,事不宜遲, 我們開始剝離回 the layer that has been string for some time. 已經作為層 串持續一段時間。 And what did we say a string actually is last week? 並沒有說什麼一個字符串 上週居然是? So char star. 因此,焦炭的明星。 And char star, well, what did that really mean? 和CHAR星,那麼, 這樣做究竟意味著什麼? Well, all this time, if we've been calling a function, 那麼,這一切的時候,如果我們已經 被調用的函數, like getString, and storing the so-called return 喜歡的getString和存儲 所謂返回 value of getString in a variable-- it's called 的getString的價值 變量 - 這就是所謂的 s type string-- we've been writing the line of code up there above. S型string--我們已經寫 這行代碼在那裡上面。 And it's only when I see my handwriting magnified here 而且它是只有當我看到我的 在這裡手寫放大 do I realize just how atrocious this is. 我意識到多麼惡劣,這是。 >> However, let's assume that, on the right-hand side >> 但是,讓我們假設, 在右手側 is, nonetheless, a reasonable depiction of what's 是,但是,合理的 一個什麼樣的描述 been going on all this time with getString. 一直在進行這一切 時間的getString。 getString, of course, gets a string. 的getString,當然,得到的字符串。 But what does that really mean? 但是,這究竟意味著什麼? It means it gets a chunk of memory from the operating system 這意味著它得到了一大塊 來自操作系統的內存 by calling a function, called malloc. 通過調用一個函數,稱為malloc的。 But more on that later. 但後來更多。 And then it populates that chunk of memory 然後填充 該內存塊 with the letters the user has typed in, followed by, of course, 以字母的用戶具有 當然鍵入,緊接著,, a null character, or backslash zero at the very end. 一個空字符或反斜杠 零在最後。 >> Meanwhile, on the left-hand side of this story, all this time, >> 同時,在左手側 這個故事,這一切的時候, we've been declaring a variable, like s. 我們已經聲明了一個變量,如第 And that variable is what now will start calling a pointer. 而這個變量就是現在 將開始調用的指針。 It's not a box inside of which we put the string, Daven, per se, 這不是這裡面一箱 我們把串,Daven,本身 but rather we put in that square box on the left what exactly? 而是我們把在這方 箱體左側究竟是什麼? Yeah? 是嗎? >> AUDIENCE: The address of where it's located in memory. >> 聽眾:的地址 它位於內存中。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 The address of where Daven is located in memory. Daven的所在地址 位於存儲器。 And not where all of Daven is located, per se, but specifically the address 不,所有Daven的所在, 本身,而是專門的地址 of what? 什麼? Yeah? 是嗎? >> AUDIENCE: First character. >> 聽眾:第一個字符。 >> DAVID J. MALAN: The first character in Daven, which, in this case, >> 戴維·J·馬蘭:第一個字符 在Daven,其中,在這種情況下, I proposed was arbitrarily and unrealistically 1, Ox1, 我提出了任意 和不切實際1,OX1, which just means the hexadecimal number of 1. 它的意思是, 1的十六進制數。 But it's probably going to be a much bigger number 但是,它可能會 是一個更大的數字 that we might draw with a 0x as a prefix, 我們可能會得出 以0X作為前綴, representing a hexadecimal character. 代表一個十六進制字符。 And because we don't need to know where the rest of the characters of Daven 而且,由於我們並不需要知道在哪裡 Daven的字符的其餘部分 are, because of what simple design decision that was made many years ago? 是因為,有什麼簡單的設計 決定這是多年前? Yeah? 是嗎? >> AUDIENCE: Backslash 0. >> 聽眾:反斜杠0。 DAVID J. MALAN: Yeah, exactly. 戴維·J·馬蘭:是的,沒錯。 The backslash 0 allows you, albeit in linear time, to traverse the string, 反斜線0可以讓你,儘管在 線性時間,來遍歷字符串 walk from left to right, with a for loop, or a while 由左到右行走, 用for循環,或同時 loop, or something like that, and determine, oh, here 環或類似的東西 這一點,決定了哦,這裡 is the end of this particular string. 是這個特定字符串的結尾。 So with just the address at the beginning of a string, 所以只用在地址 字符串的開始, we can access the entirety of it, because all this while, 我們可以訪問的全部 它,因為這一切的同時, a string has just been a char star. 一個字符串,剛剛一個char明星。 >> So it's certainly fine to continue using the CS50 library and this abstraction, >> 因此,這的確精緻繼續使用 在CS50庫,而且這樣的抽象, so to speak, but we'll begin to see exactly 可以這麼說,但我們會 首先,看看到底 what's been going on underneath this whole time. 什麼是怎麼回事 下面這整個時間。 So you may recall this example, too, from last time, compare 0, 所以,你可能還記得這個例子中, 同樣,從去年的時候,比較0, which didn't actually compare. 這實際上並沒有進行比較。 But we began to solve this. 但是,我們開始解決這個問題。 >> But as perhaps a refresher, might I interest someone >> 但是作為也許是複習, 我可能感興趣的人 in a pink elephant today, also made by Chang? 粉紅色的大象的今天, 還長呢? How about you in front? [INAUDIBLE]. 怎麼樣,你在前面? [聽不清]。 Come on up. 上來吧。 >> And in the meantime, as you come up, let's >> 並且在此期間, 你上來,讓我們 consider for just a moment what this code was actually doing. 考慮了一會兒就好了什麼 這段代碼實際上做的事情。 It's declaring two variables up top, s and t, and calling getString. 它聲明兩個變量了 頂,S和T,並調用的getString。 This isn't a very user-friendly program, because it doesn't tell you what to do. 這不是一個非常用戶友好的程序, 因為它不會告訴你的事。 But let's just assume we're focusing on the juicy part. 但是,讓我們姑且我們 重點是多汁的一部分。 And then we do, if s equals equals t, it should say printf, 然後我們做的,如果s等於 等於T,應該說printf的, you typed the same thing. 您鍵入同樣的事情。 Hello. 你好。 What's your name? 你叫什麼名字? >> JANELLE: Janelle. >> 詹妮爾:詹妮爾。 DAVID J. MALAN: Janelle, nice to meet you. 戴維·J·馬蘭:詹妮爾, 很高興認識你。 So your challenge at hand for this elephant 所以,你在挑戰 手這頭大象 is to first draw us a picture of what's being represented in those first two 是第一個吸引我們的是什麼圖片 被代表的前兩個 lines. 線。 So s and t might be represented how on the screen? 因此,S和T可能是 顯示在畫面上如何? And you can just draw it with your finger on this big screen. 而且你可以繪製與 將手指放在這個大屏幕上。 >> So there's two halves to each side of that equation. >> 因此,有兩部分,以 該方程的每一側。 So there's s on the left, and then getString on the right. 所以有S上的左側,並且 然後GetString的右邊。 And then there's t on the left, and then getString on the right. 再有就是噸左邊, 然後GetString的右邊。 So how might we begin drawing a picture that 那麼我們如何開始 繪製的畫面, represents what's going on here in memory, would you say? 表示這是怎麼回事 這裡的記憶,你會說什麼? And let me let you explain what you're doing as you go. 讓我讓你解釋 你在做什麼,當您去。 >> JANELLE: OK. >> 詹妮爾:好的。 Well, first, it would be asking you to get the input string. 嗯,首先,它會問 你得到輸入字符串。 And it would store-- oh, sorry. 它會store--哦,對不起。 DAVID J. MALAN: OK. 戴維·J·馬蘭:確定。 Good. 好。 And this is called what? 而這個叫什麼? Oh, OK. 哦,好吧。 Keep going. 繼續前進。 I didn't mean to interrupt. 我不是故意要打斷。 JANELLE: Sorry. 詹妮爾:對不起。 So it would input it into the address of-- not sure. 因此,將其輸入到 地址of--不能確定。 I can't exactly remember the number, but I believe it was starting with 0. 我不記得確切的數字, 但我相信這是從0開始。 >> DAVID J. MALAN: That's all right, because I made the numbers up, >> 戴維·J·馬蘭:沒關係, 因為我做的數字了, so there's no right answer. 所以沒有正確的答案。 >> JANELLE: Starting with the 0 arc. >> 詹妮爾:用0起弧。 >> DAVID J. MALAN: OK, so element 0. >> 戴維·J·馬蘭:好了,元素0。 Sure. 當然。 >> JANELLE: And then if was like just a two-letter-- >> 詹妮爾:然後如果是 像剛才兩個letter-- >> DAVID J. MALAN: OK, back to you. >> 戴維·J·馬蘭:好了,還給你。 >> JANELLE: So element 0, and then element 1 or element 2. >> 詹妮爾:所以元素0, 然後元件1或元件2。 DAVID J. MALAN: And which piece of the picture are you drawing right now? 戴維·J·馬蘭:而且這一塊 圖片是你畫的權利嗎? The call to getString? 給GetString的調用? Or the declaration of s? 或s的聲明? >> JANELLE: The declaration of s, I believe. >> 詹妮爾:報關 的S,我相信。 Oh, the getString, because it would be inputted into each [? area. ?] 哦,對的getString,因為它會 被輸入到每一個[?區。 ?] >> DAVID J. MALAN: Good. >> 戴維·J·馬蘭:好。 Exactly. 沒錯。 Even though this effectively returns an array, recall, 儘管這有效地 返回一個數組,調用, when we get back a string, we can index into that string using 01 and 2. 當我們回到一個字符串,我們可以 索引使用01和2的字符串。 Technically, these are probably represented by individual addresses, 從技術上講,這很可能是 個別地址表示, but that's fine. 但是這很好。 >> So suppose, if I can just fast forward to where we left off >> 於是想,如果我可以快 轉發給我們留下了 last time, if one of the strings was g a b e, 最後時刻,如果一個 字符串是克A B E, backslash 0, thereby representing gabe's input, how might we represent s now? 反斜杠0,從而表示Gabe的 輸入,怎麼可能,我們代表就談到? If this is the memory that's been returned by getString? 如果是這樣的存儲器那 被送回了的getString? >> JANELLE: Would it be represented by an arc? >> 詹妮爾:這將是 由電弧所表示? >> DAVID J. MALAN: By an arc? >> 戴維·J·馬蘭:通過電弧? Well, no. 哦,不。 Let's just say, pictorially, let me just go ahead 遠的不說,形象地, 讓我繼續前進 and propose that, if this is s, this is the return value of getString. 和建議,如果這是秒,這 是的getString的返回值。 And you've drawn this as 0, 1, 2, which is perfectly reasonable, because we 而你畫這是0,1,2,其中 是完全合理的,因為我們 can index into the string, as such. 可以索引到字符串,作為這樣。 But just to be consistent with last time, let me go ahead 但剛需一致 最後一次,讓我先走 and arbitrarily propose that this is address 1, this is address 2, 並隨意提出這 是地址1,這是地址2, this is address 3, and so forth. 這是地址3,依此類推。 And so, just to be super clear, what's going 因此,剛需超 顯然,這是怎麼回事 to go in s as a result of that first line of code, would you say? s中去,作為一個結果, 代碼的第一行,你會說什麼? >> JANELLE: Address 1? >> 詹妮爾:地址1? >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 So address 0x1. 因此,解決為0x1。 And meanwhile, let me go ahead and duplicate much of what you've done 而與此同時,讓我繼續前進, 重複的很多東西,你做 and add my own t here. 在這裡添加自己噸。 If I were to type in gabe again, a second time, 如果我要在加布型 再一次,第二次, when prompted with getString, where, of course, is gabe going to go? 當用的getString提示,其中, 當然,被加布要去? Well, presumably-- 那麼,presumably-- >> JANELLE: Like on here? >> 詹妮爾:像在這裡? DAVID J. MALAN: Yeah. 戴維·J·馬蘭:是的。 JANELLE: Or it's also in the same boxes? 詹妮爾:或者它也是在同一個箱子? DAVID J. MALAN: Let me propose, yeah, exactly, so in these additional boxes. 戴維·J·馬蘭:我建議,是啊, 準確,因此,在這些附加的盒子。 But what's key now is that, even though I've drawn these pretty close 但是,什麼是現在的關鍵是,即使 雖然我畫這些八九不離十 together-- 0x1, this is 0x2-- in reality, together--為0x1,這 被0x2--在現實中, this now might be address 0x10, for instance, and 0x11, and 0x12, 這個現在可能是地址為0x10, 例如,和為0x11,以及0x12的 and so forth. 等等。 And so, if that's the case, what's going to end up here in t? 因此,如果是這樣的話, 這是怎麼回事結束了在這裡噸? >> JANELLE: 0x10? >> 詹妮爾:為0x10? DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 So 0x10. 因此,為0x10。 And so now, final question. 所以現在,最後一個問題。 You have, by far, had to work the hardest for an elephant thus far. 你有,到目前為止,已經工作了 最難的大象迄今。 By now, if I pull up the code again, when I do, in line three, 事到如今,如果我拉起碼 再次,當我這樣做,在三線, if s equals equals t, what am I actually comparing that we've drawn here? 如果s等於等於T,我算什麼實際 相比較,我們在這裡畫? >> JANELLE: The two addresses? >> 詹妮爾:這兩個地址? DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 So I'm saying is s equal equal to t? 所以,我要說的是S等於等於t? In other words, is 1 equal equal to 10? 換句話說,是1等於等於10? And of course, the obvious answer now is, no. 並且,當然,在 答案很明顯,現在是,沒有。 And so this program is ultimately going to print what, would you say? 所以這個方案最終是 要打印的內容,你會說什麼? >> JANELLE: Would it be, you typed the same thing? >> 詹妮爾:它會是這樣, 您鍵入同樣的事情? >> DAVID J. MALAN: So if s is 1 and t is 10? >> 戴維·J·馬蘭:所以,如果 s是1和t是10? >> JANELLE: You typed different things. >> 詹妮爾:輸入不同的事情。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 You typed different things. 你輸入不同的事情。 All right. 好吧。 So a round of applause, if we could, here. 所以,掌聲雷動, 如果我們能在這裡。 [APPLAUSE] [掌聲] That was painful. 這是痛苦的。 I know. 我知道。 Nicely done. 很好地完成。 So now let's see if we can't tease apart what the fix was. 所以,現在讓我們來看看,如果我們不能 梳理出什麼樣的修復程序。 And of course, when we fixed this-- which I'll now represent in green-- 當然,當我們固定this-- 現在我將代表green-- we did a couple of enhancements here. 我們做了幾個增強功能在這裡。 First, just as a sanity check, I'm first checking 首先,正如一個理智 檢查一下,我先檢查 if s equals null and t equals null. 如果s等於null和T等於null。 And just to be clear, when might s or t be null in code like this? 而只是要清楚,如果可能 s或t為null,在這樣的代碼? When might s or t be null. 當可能s或t為null。 Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 If the string that the user typed in is way too long 如果字符串用戶 鍵入的是太長時間 to fit into memory, or some weird corner case like that, 要裝入內存,或者一些 奇怪的角落情況下那樣, getString, as we'll see, literally today, in its documentation, GetString的,正如我們所看到的,從字面上 今天,它的文檔中, says it will return null as a special sentinel value, 表示將返回null作為 一個特殊的標記值, or just sort of a special symbol that means something went wrong. 或者只是有點特殊符號 這意味著出事了。 So we want to check for that, because it turns out 因此,我們要檢查 是,因為事實證明 that null is a very dangerous value. 那空是一個非常危險的價值。 >> Often, if you try to do something with null involving a function-- passing it >> 通常情況下,如果你嘗試做一些與 空涉及函數 - 它傳遞 as input, for instance-- that function might very will crash and, with it, 作為輸入,對instance--該功能 很可能會崩潰,並用它, take down your whole program. 記下你的整個程序。 So this third line now is just a sanity check, error checking, if you will. 因此,這第三條線,現在僅僅是一個理智 檢查,檢查錯誤,如果你願意。 That's a good habit now for us to get into any time we 這是一個好習慣,現在的 我們進入任何時候我們 try to use a value that could, potentially, be null. 嘗試使用一個值, 可能,可能,是空的。 >> Now, in the fourth line here, "if strcmp(s, t)," well, >> 現在,在第四行此處, “如果STRCMP(S,T),”好了, what's that referring to? 那是什麼指? Well, we said this was a very succinctly named function for string comparison. 好吧,我們說這是一個非常簡潔 命名函數的字符串比較。 And its purpose in life is to compare its first argument against it second, 及其在生命的目的是比較 其反對的第一個參數第二, but not in terms of their addresses, as we did unintentionally a moment 但不是在它們的地址而言, 因為我們沒有無意中片刻 ago with the red code, but rather to compare those two 以前的紅色代碼,但 而比較這兩個 strings in the humanly intuitive way by comparing this, against this, 在力所能及直觀的字符串 通過比較這一點,對這種方式, against this, against this, and then stopping if and when one 針對這一點,針對這一點,並 然後停止,如果和當一個 or both of my fingers hits a backslash 0. 還是我的兩個手指 打一個反斜杠0。 So someone years ago implemented strcmp to implement for us the functionality 因此,有人年前實施的strcmp 實現我們的功能 that we hoped we would have gotten by just comparing two simple values. 我們希望我們會得到 僅通過比較兩個簡單的值。 >> Now frankly, I keep drawing all of these various numbers. >> 現在,坦率地說,我把圖紙 所有這些不同的數字。 But the reality is, I've been making these up the whole time. 但現實是,我已經 製備這些向上的全部時間。 And so let me just go ahead and scribble these out 因此,讓我乾脆去 而這些亂塗出來 to make a point that, at the end of the day and moving forward, 做一個點,在結束 這一天,並向前走, we're not really going to care about what addresses things are actually 我們不是真的要關心 有什麼解決的事情,其實 in memory. 在存儲器中。 So I'm not going to draw these kinds of numbers so much anymore, 所以,我不會畫這些 種數的那麼多了, I'm just an abstract this away a little more friendly with just arrows. 我只是一個抽象的這個客場 小只箭更友好。 >> In other words, if s is a pointer, well, let's just draw it, literally, >> 換言之,如果s是一個指針, 好了,讓我們只繪製它,從字面上看, as a pointer, an arrow pointing from itself to something else, 作為一個指針箭頭指向 從自身到別的東西, and not worry too much more about the minutia of these addresses 而不用太擔心更多 這些地址的細節 which, again, I made up anyway. 其中,再次,我反正做了。 But we'll see those addresses, sometimes, when debugging code. 但是,我們可以看到這些地址, 有時,調試代碼的時候。 >> Now meanwhile, this program up here fixes, of course, >> 現在,同時,該計劃 當然,在這裡的修復, that problem by comparing those two strings. 通過比較該問題 這兩個字符串。 But we ran into another problem. 但是,我們遇到了另一個問題。 This was from the copy program last time, 這是從複製 節目最後一次, whereby, I was trying to capitalize just the first character in a string. 因此,我試圖利用 在一個字符串僅僅是第一個字符。 But what was the symptom we saw last time when 但究竟是什麼症狀 我們看到最後的時候 a user typed in a value, like gabe in lowercase, for s, 用戶鍵入一個值,如 加布於小寫的S, then we assigned s into t, as in the third line there, 那麼我們分配s轉換T, 如第三行那裡, and then I tried to capitalize t bracket 0? 然後我試圖 資本噸支架0? What was the effect of changing t bracket 0 here? 什麼效果 改變噸支架0嗎? >> AUDIENCE: It changed s. >> 聽眾:它改變了第 >> DAVID J. MALAN: Yeah, I changed s, as well. >> 戴維·J·馬蘭:是啊, 我換了S,以及。 Because what was really going on? 因為什麼怎麼回事? Well, let me see if I can clean up this picture, as follows. 好吧,讓我看看,如果我能清潔 這幅畫,如下所示。 >> If s is, again, the word g, a, b, e, backslash, 0, and s >> 如果S是再次,字克, A,B,E,反斜杠,0和s we'll continue drawing as a box here, but no more addresses. 我們將繼續繪製一個框 在這裡,但沒有更多的地址。 Let's stop making things up. 讓我們停止做的事情了。 Let's just draw a picture to simplify the world. 讓我們只畫一幅畫 簡化了世界。 >> When I declare t with string t, that creates that chunk of memory. >> 當我宣布噸,串T, 創建的內存塊。 Square happens to be 32 bits in most computers. 方碰巧是32 位在大多數計算機上。 In fact, if you've ever heard of a computer having a 32-bit architecture, 事實上,如果你曾經聽說過的 具有32位體系結構的計算機, really fancy-speak, that just means it uses 32-bit addresses. 真正看中的,說話,只是 意味著它採用32位地址。 And as a technical aside, if you've ever wondered 而作為一個技術不談, 如果你曾經想知道 why older computers, if you actually tried to soup them up with lots of RAM, 為什麼舊的電腦,如果你真的 想喝湯起來,有很多的RAM, could only have a maximum of four gigabytes of RAM, 只能有一個最大 四個千兆字節的RAM, well that's because, literally, your old computer could only 好,這是因為,從字面上看, 您的舊電腦只能 count as high as 4 billion, 4 billion bytes, 計高達4 十億,4個十億字節, because it was using 32-bit numbers for addresses. 因為它是使用32位 號碼的地址。 >> But in any case, in this example, story's much simpler. >> 但在任何情況下,在該 比如,故事中的要簡單得多。 t is just another pointer, or really a char star, aka string. t是只是一個指針,或 真是一個char星,又名字符串。 And how do I want to update this picture now with that second line of code, 怎麼辦我想更新這幅畫 現在的代碼,第二行, after the dot, dot, dot? 點後,點,點? When I do string t equals s semicolon, how does this picture change? 當我做串T等於Š分號, 請問這張照片改變? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Yeah. >> 戴維·J·馬蘭:是的。 Exactly. 沒錯。 I just put an arrow from the t box to the same address, 我只是把一個箭頭從 噸方塊以相同的地址, the same first letter in gave. 在相同的第一個字母給了。 Or technically, if this guy were still at 0x1, 或在技術上,如果這 男人仍然在為0x1, it's as though I had 0x1 here and 0x1 here. 這是因為雖然我有 這裡為0x1和0x1這裡。 But again, who cares about the addresses? 但同樣,誰在乎 關於地址? It's just the idea that now matters. 只是,現在最重要的想法。 So this is what's happening here. 因此,這是這裡發生了什麼。 So of course, if you do t bracket 0, which is array notation, 所以,當然,如果你做T支架 0,這是數組符號, of course-- and frankly, it looks like there's an array over here, 的course--坦率地說,它看起來 像有一個數組在這裡, but now there's this weird thing. 但現在有這樣奇怪的事情。 Know that the programming language, C, offers you this feature, 要知道,編程語言, C,為您提供此功能, whereby, even if t is a pointer, or s is a pointer, 由此,即使t是 指針,或s是一個指針, you can still use that familiar, comfortable square bracket 您還可以使用熟悉的, 舒適的括號 notation to go to the first element, or the second element, or any element 符號去的第一要素, 或所述第二元件,或任何元件 that that pointer is pointing to because, presumably, it 在該指針指向 到,因為,據推測,它 is, as in this case, pointing at some array. 是,因為在這種情況下, 指著一些數組。 >> So how do we fix this? >> 那麼,我們如何解決這個問題? Frankly, this is where it got a little overwhelming at first glance. 坦率地說,這是它得到了 有點麻煩第一眼。 But here is a new and improved version. 但這裡是一個新的和改進的版本。 >> So first, I'm getting rid of the CS50 library, >> 因此,首先,我越來越 擺脫CS50庫, just to expose that s is indeed a char star, just a synonym. 只是揭露S是真的 一個char明星,只是一個代名詞。 And t is also a char star. 和T也是一個char明星。 But what is going on on the right-hand side of that line 但對到底是怎麼回事 該行的右手側 where t is assigned a value? 其中T是賦值? >> What is malloc? >> 什麼是malloc的? What it's strlen? 什麼是strlen的? What is sizeof(char)? 什麼是的sizeof(char)的? Why the heck does this line look so complex? 為什麼非得這樣做 線看起來那麼複雜嗎? What's it doing at a high level? 它是什麼做在一個較高的水平? What's it storing in t? 什麼是存儲在T? Yeah? 是嗎? AUDIENCE: It's allocating a certain amount of memory space. 聽眾:它的分配 一定量的存儲空間。 It's to store, I guess, letters [INAUDIBLE]. 它的存儲,我想, 信[聽不清]。 >> DAVID J. MALAN: Perfect. >> 戴維·J·馬蘭:完美。 Perfect. 完美的。 It's allocating a certain amount of memory space 它分配一個特定的 存儲空間量 to store, presumably, future letters. 存儲,據推測,未來的信件。 And in particular, malloc is therefore returning what? 並且特別地,malloc的 因此,返回什麼? >> AUDIENCE: Returning the [INAUDIBLE]? >> 聽眾:返回的[聽不清]? DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 Returning the address of that memory, which is a fancy way of saying, 返回的內存地址, 這只不過是一個奇特的方式, returns the address of the first byte of that memory. 返回的地址 該內存的第一個字節。 The onus is on me to remember how much memory I actually 的責任是我記住 實際上有多少內存I allocated or asked malloc for. 分配或要求的malloc的。 >> Now how much is that? >> 現在是多少呢? Well, even though there's a lot of parentheses here, 好吧,即使有 很多括號在這裡, malloc takes just a single argument. malloc的只需要一個參數。 And I'm specifying strlen of s, so give me as many bytes as there are in s, 和我指定的字符strlen,所以給 我盡可能多的字節,因為在S, but add one. 但新增一個。 Why? 為什麼呢? Yeah? 是嗎? >> AUDIENCE: The backslash 0. >> 聽眾:反斜杠0。 DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 We've got to do a little housekeeping. 我們必須做一點家務。 So because there's a backslash 0, we'd better remember that. 所以,因為有一個反斜杠 0,我們最好記住這一點。 Otherwise, we're going to create a string that 否則,我們將 創建一個字符串, doesn't have that special terminator. 沒有特別的終結者。 >> Meanwhile, just to be super anal, I have sizeof(char), >> 同時,剛需超 肛門,我的sizeof(char)的, just in case someone runs my code not on the CS50 appliance, 萬一有人跑我 不上CS50設備代碼, but maybe a different computer altogether where chars 但也許在不同的計算機 乾脆在那裡字符 are one byte, by convention, but two bytes, or something bigger than that. 是一個字節,按照慣例,但有兩個 字節或更大的東西不止這些。 It's just to be super, super averse to errors. 這是剛需超, 超級反感的錯誤。 Even though, in reality, it's most likely going to be a 1. 儘管,在現實中,這是 最有可能將是一個1。 >> Now, meanwhile, I go ahead and copy the string, t bracket i equals t bracket s. >> 現在,同時,我繼續和複製 字符串,T支架i等於噸支架第 And I will defer to last week's source code to see what's going on. 我將按照上週的 源代碼,看看是怎麼回事。 But the key takeaway, and the reason I put the code now in green, 但關鍵的外賣,以及 我之所以把代碼現在綠, is because that very last line, t bracket 0 equals toupper, 是因為很最後一行 噸支架0等於TOUPPER, has the effect of capitalizing which string? 具有的效果 轉增股本的字符串? t and/or s? T和/或S? That last line of code. 最後一行代碼。 >> Just t, because what's happened this time, >> 只是T,是因為什麼 最少此時, if I slightly undo that last step, what's happened is, when I call malloc, 如果我稍微撤消最後一步, 什麼情況是,當我調用malloc, I essentially get a chunk of memory that is the same size as the original, í基本上得到一個內存塊 這是相同的尺寸,原來, because that's the arithmetic I did. 因為這是算術我做到了。 I'm storing in t the address of that chunk of memory. 我存儲在T地址 的內存塊。 Even though this looks nice and pretty, nice and blank, 儘管這看起來不錯 漂亮,漂亮,一片空白, the reality is there's, what we'll keep calling, garbage values in here. 實際情況是有,我們會 保持通話,在這裡的垃圾值。 That chunk of memory might very well have been used before, 該內存塊可能很 也有之前被使用, a few seconds, a few minutes ago. 幾秒鐘,幾分鐘前。 So there could absolutely be numbers or letters there, just by accident. 因此,有可能完全是數字 或字母那裡,只是偶然。 But they're not valid, until I myself populate this chunk of memory 但他們不是有效的,直到我 我自己填充此塊內存 with actual chars, as I do in that for loop there. 與實際的字符,如我 做在for循環出現。 All right? 好吧? >> So now, the climax of these three examples >> 所以,現在的高潮 這三個例子 that were seemingly broken last time, this Swap example, this function 那名看似打破最後一次, 這個互換的例子,這個功能 worked in the sense that it swapped a and b. 在這個意義上製作 它交換a和b。 But it didn't work in what other sense? 但它並沒有什麼其他意義的工作? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 If I were to call this function from another-- for instance, 如果我要調用這個函數 從another--例如 from a function like main, where I have a variable, x and y, as I 從主一樣,在功能 我有一個變量,x和y,當我 did last week, same code, and I pass in x and y 上星期,同樣的代碼, 而我通過在X和Y to Swap, and then call Swap-- this, of course, is the correct version 以交換,然後調用Swap--這一點, 當然是正確的版本 is what we're about to see-- it did not work. 就是我們即將 see--沒有奏效。 So what is the fix? 那麼,什麼是定位? >> Well, so just to be clear, let me go ahead >> 好了,所以才要 顯然,讓我先走 and-- give me one second here, and see if I can show you the last one, which 還有 - 給我1秒在這裡,看 如果我能告訴你的最後一個,這 will be in-- let's see if I can find this real fast-- OK, [INAUDIBLE]. 將in--讓我們來看看,如果我能找到 這種真正的fast--確定,[聽不清]。 OK, there it is. 好了,它就在那裡。 So ignore the commands I'm just typing. 所以忽略我只是鍵入命令。 I want it to retrieve at the last minute an example 我希望它在檢索 最後一分鐘的一例 from last time, which is now called no Swap. 從去年的時間,這 現在所謂的無交換。 >> So no Swap is where we left off last time, >> 因此,沒有交換的地方 我們離開的最後一次, whereby, I initialized x to 1 and y to 2. 因此,我初始化 X要1和y 2。 I then call Swap, passing in 1 and 2. 後來我打電話交換,傳遞1和2。 And then this function worked in some sense, 然後這個函數 在某種意義上工作, but it had no permanent effect on x and y. 但它沒有永久的 在x和y的影響。 So the question at hand is, how now do we actually fix this problem? 因此,目前的問題是,怎麼現在 我們其實解決這個問題? What is the solution at hand? 如何解決在眼前? >> Well, in swap.c, which is new today, notice a couple of differences. >> 那麼,在swap.c,今天是新的, 看到一對夫婦的差異。 x and y are the same. x和y是相同的。 But what is clearly different about line 25? 但顯然 約25行有什麼不同? What's new there, if you remember what it looked like a second ago? 最新消息那裡,如果你還記得 它看起來像一秒鐘前? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Yeah. >> 戴維·J·馬蘭:是的。 So the ampersands are a new piece of syntax not only in this program, 所以連字號是一個新的作品 語法不僅這個程序中, but also more generally in CS50. 而且更普遍的CS50。 To date, I don't think we've seen any examples 到目前為止,我不認為 我們見過的任何實例 or really talked about them in any detail, other than, maybe, preemptively 還是真的在任何談論他們 細節,不是,也許,搶先其他 in section, an ampersand like this. 在節中,像這樣的符號。 Well, it turns out ampersand is one of the last pieces of new syntax 嗯,原來符號是 最後張新語法 we're going to learn. 我們要學習的。 All it means is the address of some variable. 它的意思是在 一些變量的地址。 At what address does x live? 請問您的地址並點¯x住在哪裡? But what address does y live? 但ÿ住什麼地址? Because if the fundamental problem before 因為如果 之前根本問題 was that x and y were being passed as copies, what we really want to do 在x和y分別被傳遞 作為副本,我們真正想做的事 is provide Swap with like a treasure map that leads to where x and y actually 是提供交換與像寶貝一樣 地圖,導致其中x和y實際上 are in RAM, so that Swap can follow that map 在RAM中,從而使 交換可以按照該圖 and go to wherever x or y marks the spot and change the actual values 1 and 2 和去哪裡x或y標誌的地方 和改變實際值1和2 there. 那裡。 >> So Swap needs to change slightly too. >> 所以交換需要稍微改變了。 And at first glance, this might seem a little similar to char star. 乍看之下,這可能 似乎有點類似於字符的明星。 And indeed it is. 的確是。 So a is a pointer to what type of data, based on this highlighted portion? 所以a是一個指向什麼類型的數據, 在此基礎上突出部分? So it's an int. 所以這是一個int。 >> So a is no longer an int, it's the address of an int. >> 所以不再是一個int, 這是一個int的地址。 And similarly, b is now going to be the address of an int. 同樣,B現在準備 是一個int的地址。 So when I now call Swap from Main, I'm not going to give Swap 1 and 2. 所以,當我現在請交換從主, 我不會給交換1和2。 I'm going to give it like Ox-something and Ox-something, 我要去給它像 牛的東西,黃牛的東西, two addresses that will lead Swap to their actual locations 兩個地址,這將導致 交換自己的實際位置 in my computer's memory. 在我的電腦的內存中。 >> So now, my remaining implementation needs to change a tad. >> 所以,現在,我剩下的落實 需要改變一點點。 What's obviously different now in these three lines of code? 有什麼明顯的不同,現在 在這三行代碼? There's these damn stars all over the place, all right? 有這些該死的明星都 過的地方,好嗎? So what's going on here? 所以,這是怎麼回事嗎? Yeah? 是嗎? >> AUDIENCE: It's obviously [INAUDIBLE]. >> 聽眾:這是很明顯[聽不清]。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 So in this context-- and this was not the best design decision, admittedly, 所以在此context--,這是不 最好的設計決定,無可否認, years ago. 幾年前。 In this context, where you just have a star, 在這種情況下,其中 你只需要一個明星, and you don't have a data type, like int, immediately to the left, 而你沒有的數據類型, 如int,立即到左邊, instead you have an equal sign, clearly, in this context, when you say star a, 而不是你有一個等號,顯然, 在這種情況下,當你說星A, that means go to the address that's in a. 這意味著去 地址是在一個。 Follow the treasure map, so to speak. 按照藏寶圖,可以這麼說。 >> And meanwhile, in line 37, it means the same thing. >> 並且同時,在第37行, 這意味著同樣的事情。 Go to the address a, and put what there? 去的地址,並把什麼呢? Whatever is at the location that b specifies. 不管是在 地理位置使得b指定。 In other words, go to b. 換句話說,去到b。 Get that value. 獲得該值。 Go to a and, per the equal sign, the assignment operator, 去和每平等 簽署,賦值運算符, put that value there. 把該值存在。 >> Similarly, int temp is just an int. >> 同樣,INT溫度僅僅是一個int。 Nothing needs to change about temp. 沒有什麼需要改一下溫度。 It's just a spare glass from Annenberg for some milk or orange juice. 這只是一個備用的玻璃從安嫩伯格 對於一些牛奶或橙汁。 But I do need to say, go to b. 但我需要說的,去到B。 Go to that destination and put the value in temp there. 去那個目的地, 放在那裡的溫度值。 So what's happening then? 因此,發生了什麼呢? When I actually call Swap this time, if this first tray here represents Main, 當我真正稱之為交換這個時候,如果 這第一盤在這裡代表主, this second tray represents Swap, when I pass ampersand x and ampersand y 當第二盤代表交換, 我通過符號x和符號ÿ from Main to Swap, just to be clear, what is this stack frame receiving? 從主來交換,只是要清楚, 這是什麼堆棧幀接收? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 The address of x and the address of y. x的地址和y的地址。 And you can think of these like postal addresses. 而你能想到的這些 如郵寄地址。 33 Oxford Street and 35 Oxford Street, and you 33牛津街和35 牛津街和你 want to move the two buildings that are at those locations. 要移動的兩棟樓 這是在這些地方。 >> It's sort of a ridiculous idea, but that's all we mean by address. >> 這有點荒謬的想法, 但是這就是我們所說的地址。 Where in the world can you find those two ints? 凡在世界上可以 你會發現這兩個整數? Where in the world can you find those two buildings? 凡在世界上你 找到這兩個建築物? So if finally, after all this time I go into today's source code and compile 因此,如果最後,畢竟這個時候我 進入今天的源代碼和編譯 Swap and run ./swap, finally, for the first time do we actually see that 交換和運行./swap,最後,為 第一次,我們確實看到, my values have indeed been swapped successfully. 我的價值觀的確有 已成功交換。 And now, we can even take note of this in, say, gdb. 而現在,我們甚至可以把 請注意這一點,比如,廣發銀行。 >> So let me go into the same file. >> 所以,讓我去到同一個文件中。 Let me go ahead and run gdb of ./swap. 讓我繼續運行./swap的GDB。 And now, in Swap, I'm going to go ahead and set a break point in Main. 而現在,在交換,我會去 未來,並設置一個斷點在主。 And now I'm going to go ahead and run the program. 現在我要去 繼續運行該程序。 And now we see my code paused at that line. 現在我們看到我的代碼 停在該行。 >> If I go ahead and print x, what should I see here? >> 如果我繼續和打印 X,我應該在這裡看到的? It's a question. 這是一個問題。 Say again? 再說一遍? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: So random numbers, maybe. >> 戴維·J·馬蘭:所以 隨機數,也許。 Maybe I get lucky, and it's nice and simple, like 0. 也許我很幸運,它的 優雅而簡單,如0。 But maybe it's some random number. 但也許這是一些隨機數。 In this case, I got lucky. 在這種情況下,我真的很幸運。 It just happens to be 0. 這恰好是0。 But it is indeed luck, because not until I 但它確實是運氣, 因為直到我 type next and then print x has that line of code, line 19, been executed. 輸入下一個,然後打印x的那 代碼行,19行,被執行死刑。 >> Meanwhile, if I type next again, and now print out y, I'm going to see 2. >> 同時,如果我輸入下一一遍, 現在打印出Y,我要見2。 Now, if I type next, it's going to get a little confusing, because now, 現在,如果我輸入下一個,它要 變得有點混亂,因為現在, the printf is going to appear on the screen, as it did. x is 1. 中的printf會出現在 在屏幕上,因為它沒有。 x是1。 >> Let's do this again. >> 讓我們再次做到這一點。 And now, here's where things get interesting. 而現在,這裡的地方 事情變得有趣。 Before I call Swap or even step into it, let's take a little peek. 在我打電話交換,甚至一步 進去,讓我們一點點偷看。 x is, again, 1. x是,再次,1。 Y is, of course, quick sanity check, 2, so not hard there. Y是當然,快清醒 檢查,2,所以並不難有。 But what is ampersand x? 但是,什麼是符號X你是否 Answer, it's kind of funky looking. 答案,它是一種時髦好看。 But the int star in parentheses is just gdp's way of saying this is an address. 但INT明星在括號只是 對這種說法GDP的方式是一個地址。 It's not an int, it's a pointer to an int, or otherwise known as an address. 它不是一個整數,它是一個指向 int或以其他方式被稱為一個地址。 >> What is this crazy thing? >> 這是什麼瘋狂的事? We've never seen something quite like that before. 我們從來沒有見過的東西 很喜歡之前。 So this is the address in my computer's memory of where x happens to live. 因此,這是在我的電腦的地址 內存,其中x恰好住。 It's Ox-something. 這是黃牛的東西。 And this is, frankly, why I've started drawing arrows, 這是坦率地說,為什麼 我開始畫箭頭, instead of numbers, because who really cares 不是數字的, 因為誰真正關心 that your int is at a particular address that's that big. 您的int是在一個特定的 地址是那麼大。 But bffff0c4, these are all indeed hexadecimal digits, 但bffff0c4,這些都是 的確十六進制數字, which are 0 through f. 這是0到f。 >> So we're not going to dwell too long on what those things are. >> 因此,我們不會過多糾纏 長在什麼地方的東西。 But if I print out y, of course, I see 2. 但是,如果我打印出Y, 當然,我看到2。 But ampersand y, I see this address. 但符號Y,我看這個地址。 And notice, for the curious, how far apart are x and y? 並請注意,為好奇, 相距多遠是x和y? You can ignore most of the address. 您可以忽略大部分的地址。 Four bytes. 四個字節。 And that's consistent with our earlier claim that how big is an int? 而這與我們的一致 早前聲稱有多大是一個int? Four bytes. 四個字節。 So it looks like everything's lining up nicely, as you might hope, in memory. 所以看起來一切都排隊 很好,你可能希望,在內存中。 >> So now, let's just fast forward to the end of this story. >> 所以,現在,讓我們快進 這個故事的結尾。 Let's go ahead and type step, to dive into the Swap function. 讓我們繼續前進,步型, 潛入交換功能。 Now notice, if I type a, it's identical to the address of x. 現在發現,如果我輸入一個,它的 相同,x的地址。 If I type b, it's identical to the address of y. 如果我B型是相同的 到y的地址。 So what should I see if I say, go to the address a? 所以,我應該怎樣,如果我看到 說,進入地址的? So print star a. 因此,打印星號標示。 So star means go there, in this context. 所以,明星意味著去那裡,在這種情況下。 Ampersand means what's the address of. &符號意味著什麼的地址。 So star a means 1. 所以,明星的手段1。 And print star b gives me 2. 並打印星級的住宿給我2。 >> And let me assume, for the moment, that at least the code that >> 讓我假設,就目前而言, 至少所述代碼 proceeds to execute now can be reasoned through in that way. 現在進入執行即可 通過這種方式的理由。 But we'll revisit this idea before long. 但我們會在不久重新討論這個想法。 So this version of Swap is now correct and allows 所以這個版本的互換 現在是正確的,並且允許 us to swap this particular data type. 我們來交換該特定數據類型。 >> So any questions then on Swap? >> 所以任何疑問然後交換? On star? 在星? On address of? 對地址? And you'll see, with problem set 4, sort of, 你會看到,有 問題集4,排序, but problem set 5, definitely, how these things are useful and get much more 但問題集5,絕對,如何將這些 東西是有用的,並得到更多的 comfortable with them, as a result. 熟悉他們,作為一個結果。 Anything at all? 什麼呢? All right. 好吧。 So malloc is, again, this function that just allocates memory, memory 所以malloc的是,再次,此功能 剛剛分配內存,內存 allocation. 分配。 And why is this useful? 以及為什麼是這樣有用嗎? Well, all this time, you've been using malloc. 那麼,這一切的時候, 你一直在使用malloc。 If you consider now how getString works, presumably, it's 如果你現在怎麼考慮的 GetString的作品,據推測,這是 been asking someone for a chunk of memory, anytime the user types a string 被問的人一大塊 記憶,隨時在用戶鍵入字符串 in, because we certainly didn't know, as CS50 staff, 在,因為我們肯定 不知道,因為CS50的工作人員, how big those strings that humans are going to type might be. 有多大的字符串,人類 要鍵入可能。 >> So let's, for the first time, start to peel back how the CS50 library works, >> 因此,讓我們,第一次,開始 剝開如何CS50庫工程, by way of a couple of examples that will lead us there. 通過幾個實例來 這將導致我們的。 So if I open up gedit and open up scanf 0, 所以,如果我打開gedit的 開拓scanf函數0, we're going to see the following code. 我們將看到下面的代碼。 Scanf 0, available on the website for today, has relatively few lines of code scanf函數0,可以在網站上 今天,有代碼相對較少的行 here, 14 through 20. 在這裡,14至20。 And let's see what it's doing. 讓我們來看看它在做什麼。 It declares an int, called x. 它聲明為int,名為x。 It says something like, number please. 它說像,數請。 And now it says, scanf %i, &x. 而現在它說,scanf函數%I,&X。 So there's a bunch of new stuff there. 因此,有一堆新的東西出現。 >> But scanf, you can kind of think of as the opposite of printf. >> 但是scanf函數,你可以種思考 作為printf的相反。 printf, of course, prints to the screen. printf的,當然,打印到屏幕上。 scanf sort of scans from the user's keyboard something he or she has typed. scanf的排序從用戶的掃描 鍵盤的東西,他或她已經打出來。 >> %i is just like printf. >> %i是一樣的printf。 This means expect the user to type an int. 這意味著預期 用戶鍵入一個int。 And now, why do you think I might be passing scanf &x? 而現在,你為什麼認為我 可能是通過scanf函數&X? If the purpose in life of scanf is to get something from the user, 如果目的在scanf生活 是得到的東西從用戶 what is the meaning of passing it, &x, now? 是什麼意思 通過它,與X,現在呢? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 Whatever I, the human, type in, my input is going to be saved at that location. 無論我,人,請在我的輸入 將被保存在該位置。 It's not sufficient, recall, to just pass in x, because we've seen already, 這是不夠的,還記得,剛 通過在X,因為我們已經看到, any time you pass just a raw variable, like an int, to some other function, 任何時候,你只需通過一個原始變量, 就像一個int,一些其他的功能, sure, it can change that variable, but not permanently. 當然,它可以改變 可變的,但不會永久。 It can't have an effect on Main. 它不能對主要的效果。 It can only change its own local copy. 它只能改變自己的本地副本。 But if, instead, you don't give me the actual int, 但相反,如果你不這樣做 給我實際的詮釋, but you give me directions to that int, I now, being scanf, 但你給我方向 在INT,我現在,是scanf函數, surely, I can follow that address and put a number there 當然,我可以按照這 解決並把一些有 so you have access to it as well. 所以你可以訪問它。 >> So when I run this program, let's see. >> 所以,當我運行這個程序,讓我們來看看。 Make scanf 0 dot slash, scanf 0. 使scanf函數0點斜線,scanf函數0。 And if I now type a number like 50, thanks for the 50. 如果我現在鍵入數字 像50,感謝50。 If I now type a number like negative 1, for the negative 1. 如果我現在鍵入數字一樣 負1,為負1。 I now type a number like 1.5, hm. 我現在鍵入數字如1.5,HM。 Why did my program ignore me? 為什麼我的程序不理我了? Well, because simply, I told it to expect an int only. 嗯,因為簡單地說,我告訴 只期待一個int。 All right. 好吧。 So that's one version of this. 所以這是其中的一個版本。 Let's take things up a notch and propose that this is not good. 讓我們拿東西了一個缺口, 提出,這是不好的。 And herein lies a very simple example of how we can start writing code 而就在這裡一個很簡單的例子, 怎麼我們就可以開始編寫代碼 that other people can exploit or compromise by doing bad things. 其他人可以利用或 做不好的事情妥協。 So line 16, so similar in spirit to before, 所以第16行,如此相似 在精神之前, but I'm not declaring it int this time. 但我不會宣布它詮釋這個時候。 I'm declaring it char star, aka string. 我宣布它炭星,又名字符串。 >> But what does that really mean? >> 但是,這究竟意味著什麼? So if I don't specify an address-- and I'm calling it arbitrarily, buffer, 所以,如果我不指定address--和 我打電話是隨意,緩衝, but I could call it s, to be simple-- and then I do this, explain to me, 但我可以把它稱為為s,是simple-- 然後我做到這一點,給我解釋一下, if you could, based on the previous logic, what is scanf doing in line 18, 如果可以的話,基於先前 邏輯是什麼scanf函數在做線18, if pass %s and buffer, which is an address? 如果傳%s和緩衝區, 這是一個地址? What is scanf, if you apply the exact same logic as version 0, 什麼是scanf函數,如果你申請的 完全相同的邏輯版本0, going to try to do here, when the user types something in? 當將試圖在這裡做, 在用戶類型的東西嗎? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Exactly. >> 戴維·J·馬蘭:沒錯。 Scanf, by the logic earlier, is going to take the string scanf函數,通過邏輯較早, 將要採取的串 that the human typed in-- it's now a string, 該人的類型化 in--它現在是一個字符串, it's not a number, presumably, if he or she cooperates-- 它不是一個數,據推測, 如果他或她cooperates-- and it's going to try to put that string in memory at whatever address 並且它會試圖把那 字符串在內存中的任何地址 buffer specifies. 緩衝區指定。 And this is great, because buffer is indeed meant to be an address. 這是偉大的,因為緩衝 的確意味著是一個地址。 >> But I claim this program is buggy in a very serious way, because what value is >> 但我要求這個節目是越野車的 很嚴肅的方式,因為價值是什麼 buffer by default? 默認情況下緩衝區? What have I initialized into? 我有什麼初始化為? What chunk of memory? 什麼的內存塊? I haven't, right? 我沒有,對不對? >> So even though I've allocated a char star that's no longer called s, >> 所以,即使我已經分配了 焦恆星的不再叫S, it's instead called, buffer-- so let's draw the variable's name 它不是所謂的,buffer--所以 讓我們來繪製變量名 now as buffer-- if I haven't called getString or malloc here, 現在的buffer--如果我沒有 所謂的getString或malloc的位置, that effectively means that buffer is just some garbage value. 這實際上意味著, 緩衝區只是一些垃圾值。 >> Now what does that mean? >> 現在是什麼意思? It means that I have told scanf to expect a string from the user. 這意味著,我已經告訴scanf函數 期望從用戶的字符串。 And you know what? 而且你知道嗎? Whatever this thing is pointing to-- and I draw question mark, 不管這件事情是指向 to--和我畫問號, but in reality, it's going to be something like Ox1, 2, 3, right? 但在現實中,這將是 像OX1,2,3,對不對? It's some bogus value that just happens to be there from before. 這是一些虛假的價值,僅僅 恰好從之前在那裡。 So put another way, it's as though buffer is just 所以,換句話說,它是 彷彿緩衝只是 pointing to something in memory. 指著東西在內存中。 I have no idea what. 我不知道是什麼。 >> So if I type in gabe now, it's going to try to put g-a-b-e /0 there. >> 所以,如果我輸入加布現在,這是怎麼回事 嘗試把G-A-B-E / 0出現。 But who knows what that is? 但誰知道這是什麼嗎? And in the past, any time we've tried to touch 和過去一樣,任何 我們試圖去觸摸時間 memory that doesn't belong to us, what has happened? 不屬於存儲器 對我們來說,發生了什麼事? Or almost every time. 或幾乎所有的時間。 Segmentation fault, right? 分段錯誤,對吧? >> This arrow, I have no idea where it's pointing. it's just some random value. >> 這個箭頭,我不知道它是 指點。它只是一些隨機值。 And of course, if you interpret a random value as an address, 當然,如果你解釋 一個隨機值作為地址, you're going to go to some random destination. 你會去 一些隨機的目的地。 So gabe might indeed crash my program in this case here. 所以加布可能確實崩潰 我在這裡這種情況下程序。 >> So what can we do that's almost as bad? >> 所以,我們可以做到這一點幾乎是壞? Consider this third and final example of scanf. 考慮這個第三和 scanf函數的最後一個例子。 This version is better in what sense? 這個版本是在何種意義上比較好? If you are comfortable with the previous problem, this is better. 如果你是舒服了 以前的問題,這是更好的。 Why? 為什麼呢? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 DAVID J. MALAN: Good. 戴維·J·馬蘭:好。 So this case of line 16 is better, in the sense 線16,以便該情況下 較好,在這個意義上 that we're explicitly allocating some memory. 我們是明確的 分配一些內存。 We're not using malloc, we're using the week 2 我們不使用malloc, 我們使用了2週 approach of just declaring an array. 只是聲明數組的方法。 And we've said before that a string is just an array of characters, 而我們在此之前一個字符串說過 是一個字符只是一個數組, so this is totally legitimate. 所以這是完全合法的。 But it's, of course, as you note, fixed size, 16. 但它的,當然,如 您注意,固定的大小,16。 >> So this program is totally safe, if I type >> 因此,這個計劃是 完全安全的,如果我輸入 in one character strings, two character strings, 15 character strings. 在一個文字串,兩個字符的 串,15字符的字符串。 But as soon as I start typing 16, 17, 18, 1,000 character strings, 但是當我開始打字16, 17,第18,千字符串, where is that string going to end up? 這裡是該字符串將要結束? It's going to end up partly here. 這將結束部分在這裡。 But then who knows what else is beyond the boundaries 但誰知道還有什麼 超出了界限 of this particular array? 這個陣列呢? >> It's as though I've declared 16 boxes here. >> 這是因為雖然我 在這裡宣布16箱。 So rather than draw out all 16, we'll just pretend that I've drawn 16. 因此,而不是畫出來的所有16中,我們將 只是假裝我畫16。 But if I then try to read a string that's much longer, like 50 characters, 但是,如果我再嘗試讀取字符串 這是更長的時間,如50個字符, I'm going to start putting a, b, c, d, x, y, z. 我要開始把 A,B,C,D,X,Y,Z。 And this is presumably some other memory segment 這大概是 其它一些內存段 that, again, might cause my program to crash, 即,再次,可能會導致 我的程序崩潰, because I've not asked for anything more than just 16 bytes. 因為我沒有要求 事情不止16個字節。 >> So who cares? >> 那麼,誰在乎呢? Well, here's the CS50 library. 好了,這裡的CS50庫。 And most of this is just like instructions up top. 而且大部分這只是 類似的指令往上頂。 The CS50 library, all this time, has had this line in line 52. 該CS50庫,這一切的時候, 已經有這一行52行。 We've seen typedef, or you will see typedef 我們已經看到的typedef,或 你會看到的typedef in pset 4, which just creates a synonym whereby char star can be more 在PSET 4,剛剛創建了一個 同義詞其中焦炭明星可以更 simply referred to as string. 簡稱為字符串。 So this is one of the few training wheels 因此,這是一個 數輪培訓 we've used secretly underneath the hood. 我們已經偷偷使用了引擎蓋下方。 >> Meanwhile, here's the function, getchar. >> 同時,這裡的函數,getchar函數。 Now apparently, there's no body to it. 現在很明顯,沒有身體吧。 And in fact, if I keep scrolling, I don't actually 而事實上,如果我繼續 滾動,我實際上並不 see any implementations of these functions. 看不到任何的實現 這些功能。 As a sanity check, why is that? 作為一個全面的檢查,這是為什麼? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 DAVID J. MALAN: Yeah. 戴維·J·馬蘭:是的。 So this is the header file. 因此,這是頭文件。 And header files contain prototypes, plus some other stuff, it seems, 和頭文件包含原型, 再加上一些其他的東西,現在看來, like typedefs. 喜歡的類型定義。 But in CS50.c, which we've never given you outright, 但在CS50.c,我們已經 從來沒有給你顧左右而言他, but has been in the CS50 appliance all this time, deep inside of its folders, 但一直在CS50所有家電 這個時候,內心深處的文件夾, notice that there's a whole bunch of functions in here. 注意到有一個整體 在這裡一堆功能。 >> In fact, let's scroll down. >> 事實上,我們向下滾動。 Let's ignore most of them, for now. 讓我們忽略了他們中的大多數現在。 But scroll down to getInt and see how getInt works. 但是,向下滾動到調用getInt 看看調用getInt是如何工作的。 So here is getInt. 因此,這裡是調用getInt。 And if you ever really cared how get int works, here is its documentation. 如果你真的關心如何獲得 INT作品,這裡是它的文檔。 And among the things it says is it tells you 而當中的事 它說的是它告訴你 what the ranges of values it can return. 什麼值的範圍就可以返回。 It's essentially negative 2 billion to positive 2 billion, give or take. 它本質上是負面的2十億 以正面的2十億,給予或採取。 >> And it turns out, all this time, even though we've never >> 而事實證明,這一切 時間,即使我們從來沒有 had you check for it, if something goes wrong, 有了你檢查它, 如果出現錯誤, it turns out that all this time, getInt has 事實證明,所有的 此時,調用getInt有 been returning a special constant, not null, 已返回一個特殊的 常量,不為空, but rather int_max, which is just a programmer's convention. 而是INT_MAX,這是 只是一個程序員的約定。 It means here is a special value. 這意味著這裡是一個特殊的值。 Make sure to check for this, just in case something goes wrong. 請一定要檢查這一點,只是 在出錯的時候。 But we've never bothered with that to date, 但是,我們從來沒有困擾 同的是,到目前為止, because again, this is meant to simplify. 因為再次,這 是為了簡化。 >> But how does getInt get implemented? >> 但如何調用getInt得到實施? Well, one, it takes no arguments. 嗯,一,它不帶任何參數。 We know that. 我們知道這一點。 It returns an int. 它返回一個int。 We know that. 我們知道這一點。 So how does it work underneath the hood? 那麼它是怎樣的引擎蓋底下工作? >> So there's apparently an infinite loop, at least the appearance of one. >> 所以這是很明顯的無限 環,其中一個至少外觀。 Notice that we're using getString. 請注意,我們使用的getString。 So that's interesting. getInt calls our own function, getString. 所以這很有趣。調用getInt 調用我們自己的函數,的getString。 And now why might this be the case? 現在為什麼會變成這樣? Why am I being defensive here in line 165? 為什麼我會被防守 在這裡行165? What could happen in line 164, just to be clear? 哪些本著可能發生 164,只是要清楚嗎? It's the same answer as before. 這是同樣的答案和以前一樣。 Might just be out of memory. 可能僅僅是內存不足。 Something goes wrong with getString, we've got to be able to handle that. 不順心的事了的getString, 我們必須能夠處理的。 And the reason I don't return null is that, technically, null is a pointer. 而我之所以不返回null是 即,在技術上,空是一個指針。 getInt has to return an int. 調用getInt必須返回一個int。 So I've arbitrarily decided, essentially, 所以我隨意 決定,從本質上講, that 2 billion, give or take, is going to be a special value that I can never 有2十億,而奮鬥,是怎麼回事 是一種特殊的價值,我永遠不可能 actually get from the user. 其實獲取用戶。 It's just the one value I'm going to waste to represent an error code. 這只是一個價值我要去 浪費,代表一個錯誤代碼。 >> So now, things get a little fancy. >> 所以,現在,事情變得有點奇特。 And it's not quite the same function as before, but it's very similar. 它不是完全一樣的功能 和以前一樣,但它是非常相似的。 So notice, I declare here, in line 172, both an int n and a char c. 所以請注意,我在這裡聲明,符合 172,無論是一個int n和一個char℃。 And then I use this funky line, sscanf, which it turns out 然後我用這個時髦的路線, sscanf的,它原來 doesn't scan a string from the keyboard. 不掃描從鍵盤輸入的字符串。 It stands an existing string that the user has already typed in. 它代表著現有的字符串 用戶已經鍵入英寸 So I already called getString, which means I have a string in memory. 所以,我已經叫的getString,這 意味著我有一個字符串在內存中。 sscanf is what you'd call a parsing function. sscanf的是什麼,你會 調用解析函數。 It looks at the string I've typed in, character by character, 它著眼於我有串 鍵入,字符一個字符, and does something useful. 並做一些有用的東西。 That string is stored in line. 該字符串被存儲在一行。 And I know that only by going back up here and saying, oh, OK, 我知道,只有通過去 備份在這裡,說,哦,好吧, I called it not s this time, but line. 我把它叫做不發這個時間,但行。 >> And now this is a little different. >> 而現在,這是一個有點不同。 But this effectively means, for reasons we'll somewhat wave our hands at today, 但是這實際上意味著,其原因 我們會有點潮手在今天, that we are checking to see if the user typed in 我們正在檢查 查看該用戶鍵入 and int and maybe another character. 與詮釋,也許另一個字符。 If the user typed in an int, it's going to be stored in n, because I'm 如果用戶輸入了一個int,它的 將要被存儲在正,因為我 passing this by address, the new trick we've seen today. 按地址傳遞這一點, 今天我們看到的新把戲。 If the user also typed in like 123x, that x 如果用戶還輸入 像123x,使得x is going to end up a letter in character c. 將要結束了 字母字符c。 >> Now it turns out that sscanf will tell me, intelligently, >> 現在事實證明,sscanf的 告訴我,智能化, how many variables was sscanf successfully able to fill. 多少個變量是sscanf的 能夠成功地填補。 So by this logic, if the function I'm implementing is getInt, 所以通過這種邏輯,如果該函數 我實施的調用getInt, but I'm checking, potentially, for the user 但我檢查, 潛在地,對於用戶 to have typed in an int followed by something else, 已經輸入了一個int 其次是別的東西, what do I want sscanf's return value truly to be? 什麼才是我想要的sscanf的 返回值真的是? If the purpose is to get just an int from the user? 如果目的是要獲得 只是從用戶的詮釋? >> So if sscanf returns 2, what does that mean? >> 所以,如果sscanf的回報 2,是什麼意思呢? The user typed in something like, literally, 用戶鍵入 是這樣,從字面上看, 123x, which is just nonsense. 123x,這只是無稽之談。 It's an error condition, and I want to check for that. 這是一個錯誤,並 我要檢查的。 >> So if the user types this in, by this logic, what does sscanf return, >> 因此,如果這在用戶的類型,由 這個邏輯有哪些呢sscanf的回報, would you say? 你會說什麼? So it's going to return 2, because the 123 is going to go in here, 所以它會返回2,因為 123是要去這裡, and the x is going to end up in here. 而X是要結束在這裡。 But I don't want the x to get filled. 但我不想在x得到填補。 I want to sscanf to only succeed in filling the first of its variables. 我想,sscanf會只成功 灌裝頭的變量。 And so that's why I want sscanf to return 1. 所以這就是為什麼我 想sscanf會返回1。 >> And if this is a bit over the head for the moment, that's totally fine. >> 如果這是有點在頭上 就目前而言,這是完全正常。 Realize though, that one of the values of getInt and getString 意識到雖然,其中一個 調用getInt和GetString值 is that we're doing a heck of a lot of error checking like this so 就是我們正在做的啦! 很多錯誤檢查這樣使 that, to date, you can pretty much type anything at your keyboard, 是,到今天為止,你幾乎可以 在你的鍵盤輸入任何東西, and we will catch it. 我們會抓住它。 And we certainly, the staff, will definitely not 我們肯定的是, 工作人員,肯定不會 be the source of a bug in your program, because we're defensively 在一個錯誤的來源你 計劃,因為我們的防守 checking for all of the stupid things that a user might do, 檢查所有的愚蠢的 的東西,用戶可能會做, like typing a string, when you really wanted int. 如輸入一個字符串,當 你真的想要詮釋。 So for now-- we'll come back to this before long-- 因此,對於now--我們就來 回此之前long-- but all this time, getString and getInt have 但是這一切的時候, 的getString和調用getInt有 been underneath the hood using this basic idea of addresses of memory. 在使用這種發動機罩下方 內存地址的基本思路。 >> So now, let's make things a little more user-friendly. >> 所以,現在,讓我們把事情 對用戶來說更加友好。 As you may recall, from Binky last time-- if my mouse will cooperate-- so 您可能還記得,從去年賓基 時間 - 如果我的鼠標會cooperate--所以 we had this code, which frankly, is fairly nonsensical. 我們有這個代碼,這 坦率地說,是相當荒謬的。 This code achieves nothing useful, but it was the example 此代碼實現了什麼 有用的,但它是例子 that professor Parlante used in order to represent 該教授Parlante 為了表示用於 what was going on in a program involving memory. 什麼樣的是怎麼回事 項目涉及內存。 >> So let's retell this story super briefly. >> 因此,讓我們複述這 故事超簡要介紹。 These first two lines, in English, do what, would you say? 這些前兩行,在 英語,做什麼,會說什麼? Just in reasonably human, but slightly technical terms, take a stab. 就在合理的人,但 稍微專業術語,取刺。 AUDIENCE: [INAUDIBLE]. 聽眾:[聽不清]。 >> DAVID J. MALAN: OK, you're establishing addresses for your x and y variables. >> 戴維·J·馬蘭:好,你確定 地址為你的x和y變量。 Not quite, because x and y are not variables in the traditional sense. 不大,因為x和y是未 變量在傳統意義上的。 x and y are addresses or will store address. x和y是地址 或者將存儲地址。 So let's try this once more. 因此,讓我們試試這個一次。 Not a bad start, though. 不是一個糟糕的開局,但。 Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 DAVID J. MALAN: Good. 戴維·J·馬蘭:好。 I think that's a little cleaner. 我認為這是一個小清潔。 Declaring two pointers, two integers. 聲明兩個三分球,兩個整數。 And we're calling them x and y. 而我們稱他們為x和y。 Or if we were to draw this as a picture, again, 或者,如果我們畫 此為圖片,再 recall quite simply that all we're doing with that first line 記得很簡單,所有 我們正在做的與第一線 is drawing a box like this, with some garbage value in it, 正在制定一個盒子這樣的, 在它的一些垃圾的價值, and calling it x, and then another box like this, 並調用它的X,然後 另一個盒子這樣的, with some garbage value in it, calling it y. 與一些垃圾值 它,叫它年。 We've declared two pointers that ultimately 我們已經聲明了兩個 三分球,最終 will store the address of an int. 將存儲一個int的地址。 So that's all there. 所以這一切都在那裡。 >> So when Binky did this, the clay just looked like this. >> 所以當賓基這樣做,則 粘土只是看著這樣的。 And Nick just kind of wrapped up the arrows, 和尼克剛種 包裹起來的箭, as though they're not pointing anywhere in particular, because they're just 彷彿他們不是指向任何地方 特別是,因為他們只是 garbage values. 垃圾值。 They're not explicitly initialized anywhere in particular. 他們沒有明確的初始化 任何地方尤其如此。 >> Now the next line of code, recall, was this. >> 現在的下一行 代碼,召回,是這樣的。 So in reasonably user-friendly, but somewhat technical English, 因此,在合理的人性化, 但有些技術英語, what is this line of code doing? 什麼是這行代碼在做什麼? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]. >> 聽眾:[聽不清]。 >> DAVID J. MALAN: Perfect. >> 戴維·J·馬蘭:完美。 It's allocating the chunk of the memory that's the size of an int. 它分配的大塊 內存是一個int的大小。 And that's half the answer. 而這一半的答案。 You answered the right half of the expression. 你回答正確 一半的表情。 What is happening on the left-hand side of the equal sign? 什麼是發生在 等號左邊? Yeah? 是嗎? AUDIENCE: And assigns it to the variable x? 聽眾:和受讓人 它給變量x? >> DAVID J. MALAN: And assigns it to the variable x. >> 戴維·J·馬蘭:和受讓人 它給變量x。 So to recap, right-hand side allocates enough memory to store an int. 總括來說,右側會分配 足夠的內存來存儲一個int。 But malloc specifically returns the address 但具體的malloc 返回地址 of that chunk of memory, which you've just proposed gets stored in x. 這大塊的內存,您已中 只是建議被存放在X。 >> So what Nick did last time with Binky is he dragged that pointer out, the clay, >> 那麼,尼克做了最後一次帶賓基是 他拖著那指針移出,粘土, to point now at a white chunk of memory that is equal to the size of an int. 現在指向一個內存塊白 等於一個int的大小。 And indeed, that's meant to represent four bytes. 事實上,這意味著 來表示四個字節。 >> Now, the next line of code did this, star x gets 42. >> 現在,代碼的下一行 這樣做,星x被42。 So 42 is straightforward on the right-hand side, meaning of life. 所以42是簡單的 右手側,生活的含義。 Left-hand side, star x means what? 左側,星x表示什麼? That too might have gone-- that's OK. 這也可能gone--沒關係。 OK. 行。 >> AUDIENCE: Basically, go to the [INAUDIBLE] >> 聽眾:基本上, 進入[聽不清] DAVID J. MALAN: Good. 戴維·J·馬蘭:好。 AUDIENCE: [INAUDIBLE]. 聽眾:[聽不清]。 DAVID J. MALAN: Exactly. 戴維·J·馬蘭:沒錯。 Left-hand side means go to x. 左手邊是指去為x。 x is address. x是地址。 It's like 33 Oxford Street, or Ox1. 這就像33牛津街,或OX1。 And star x means go to that address and put what there? 和星x表示去那家 解決和放什麼呢? 42. 42。 >> So indeed, that's exactly what Nick did. >> 所以,事實上,這正是尼克做了。 He started with by, essentially, mentally 他開始用, 本質上,精神上 pointing a finger at x, following the arrow 用手指指著 的x,下面的箭頭 to the white box on the right-hand side, and putting the number 42 there. 到右側的白框 側,並且把數42那裡。 But then things got a little dangerous, right? 但後來事情得到了 有點危險吧? Binky's about to lose his head. 賓基的即將失去他的頭。 >> Star y equals 13, bad luck, means what? >> 星y等於13,運氣不好,意味著什麼? So star y means go to the address in y. 所以,明星y表示去的地址y中。 But what is the address in y? 但是,什麼是Y中的地址? All right, it's garbage value, right? 好吧,這是垃圾的價值,對不對? I drew it as a question mark. 我畫它作為一個問號。 Nick drew it as a curled up arrow. 尼克畫了它作為一個蜷縮箭頭。 And as soon as you try to do star y, saying go there, 而且只要你嘗試 做明星Y,說去那裡, but there is not a legitimate address, it's some bogus location, 但沒有一個合法的 地址,它的一些虛假的位置, the program's going to crash. 該計劃的要崩潰。 And Binky's head is going to fly off here, as it did. 和賓基的頭部會 飛了出去,在這裡,因為它沒有。 >> So in the end, this program was just flat out flaw. >> 所以,最後,這個方案 只是平了破綻。 It was a buggy program. 這是一個錯誤的程序。 And it needed to be fixed. 它需要加以固定。 And the only way, really, to fix it would be, for instance, this line, 而唯一的辦法,真的,要解決它 將是,舉例來說,這條線, which we didn't even get to, because the program crashed too soon. 我們甚至沒有去,因為 程序崩潰得太快。 But if we were to fix this, what effect does doing y equal x have? 但是,如果我們要解決這個問題,有什麼 效果確實做Ÿ等於x具有? Well, it essentially points y at whatever value x is pointing at. 那麼,它基本上是在點ÿ 任何值x指向。 >> So in Nick's story, or Binky's story, both >> 因此,在尼克的故事, 或賓基的故事,無論是 x and y were pointing at the white chunk of memory, x和y分別為指向 白色塊的存儲器, so that, finally, when you do star y equals 13 again, 這樣一來,最終,當 做明星Ÿ再次等於13, you end up putting 13 in the appropriate location. 你最終將在13 適當的位置。 So all of these lines are perfectly legitimate, except for this one, 因此,所有這些線路都完美 合法的,除了這一個, when it happened before you actually assigned y some value. 之前,當它發生 實際分配Ÿ一定的價值。 >> Now thankfully, you don't have to reason through all >> 現在值得慶幸的是,你不 要通過推理全部 of these kinds of issues on your own. 這些類型的問題你自己。 Let me go ahead and open up a terminal window here 讓我繼續前進,開 在這裡一個終端窗口 and open up, for just a moment, a super short program that 與開拓,就一下, 超級短節目的 also is sort of pointless. 也就是那種毫無意義的。 It's ugly. 這是醜陋的。 It doesn't achieve anything useful. 它沒有實現任何用處。 But it does demonstrate issues of memory, so let's take a look. 但它確實證明問題 記憶,讓我們一起來看看。 >> Main, super simple. >> 主要的,超級簡單。 It apparently calls a function, f, and then returns 0. 這顯然是調用一個函數, F,然後返回0。 It's kind of hard to mess this up. 這是一種很難搞砸。 So Main is pretty good, so far. 所以,主要是相當不錯的,到目前為止。 >> So f is problematic. >> 所以f是有問題的。 And just didn't put much effort into naming it 只是沒放多少 努力為它命名 here, to keep the focus on the code. 在這裡,以保持重心的代碼。 f has two lines. f有兩行。 And let's see what's now going on. 讓我們看看現在怎麼回事。 So on the one hand here-- and let me make 這樣一方面 這裡 - 並讓我 this consistent with the previous example-- on the one hand, 與前此一致 example--一方面, the left-hand side is doing what, in English? 左手側是 做什麼,用英語? It is-- 它is-- AUDIENCE: Creating a pointer. 聽眾:創建一個指針。 DAVID J. MALAN: Creating a pointer to an int and calling it x. 戴維·J·馬蘭:創建一個指針 為int,把它x即可。 So it's creating one of those boxes I keep drawing on the touch screen. 因此,它的創造者一個箱子 我一直畫在觸摸屏上。 And now, on the right-hand side, malloc, of course, 現在,對右手 當然一面,malloc的, is allocating a chunk of memory. 被分配的內存塊。 And just to be clear, how much memory is it apparently 而只是要清楚,怎麼 多少內存是它明顯 allocating, if you just kind of do the math here? 分配,如果你只是 種做數學題嗎? >> So it's 40 bytes. >> 因此,它是40個字節。 And I know that only because I know an int, on the CS50 appliance, at least, 我知道,只是因為我知道的 整數,在CS50器具,至少 is four bytes. 是四個字節。 So 10 times 4 is 40. 所以,10次4 40。 So this is storing an x, the address of the first out of 40 ints that 所以這是存儲一個x,地址 第一次出40的整數 have been allocated space back, to back, to back, to back. 已分配的空間回來了, 背,背,背來。 >> And that's what's key about malloc. >> 而這正是重點對malloc的。 It doesn't take a little memory here, a little here, a little here. 它並不需要一點點內存 在這裡,有一點在這裡,在這裡一點點。 It gives you one chunk of memory, contiguously, from the operating 它為您提供了一個內存塊, 連續地,從操作 system. 系統。 >> Now what about this, x bracket 10 equals 0? >> 現在來談談這個, 點¯x支架10等於0? Arbitrary line of code. 獨斷專行的代碼。 It doesn't achieve anything useful. 它沒有實現任何用處。 But it is interesting, because x bracket 10--? 但有意思的是, 因為變量x支架10--? Yeah? 是嗎? >> AUDIENCE: [INAUDIBLE]? >> 聽眾:[聽不清]? >> DAVID J. MALAN: x bracket 10 doesn't have to be null. >> 戴維·J·馬蘭:X支架 10不必是空的。 The null detail only comes into play with strings, at the end of a string. 空的細節只有進場 用字符串,在字符串的結尾。 But a good thought. 但一個好的想法。 >> How big is this array, even though I've allocated 40 bytes? >> 有多大這個數組,甚至 雖然我已經分配40個字節? It's 0 through nine, right? 這是從0到9,對不對? It's 10 ints, total. 這10個整數,總。 40 bytes, but 10 ints, indexed 0 through 0. 40個字節,但是10個整數, 索引0到0。 >> So what is that x bracket 10? >> 那麼,什麼是是X支架10? It's actually some unknown garbage value. 它實際上是一些 未知的垃圾值。 It's memory that doesn't belong to me. 這是一個不屬於我的記憶。 I should not be touching that byte number 41, 42, 43, 44. 我不應該碰的 字節數41,42,43,44。 I'm going slightly too far. 我會稍微有點遠。 >> And indeed, if I run this program, it might very well crash. >> 事實上,如果我運行這個 程序時,它很可能會崩潰。 But sometimes, we'll get lucky. 但有時,我們會得到幸運。 And so just to demonstrate this-- and frankly, 所以,只是為了演示 this--坦率地說, you never know before you do it-- let's run this. 你永遠不知道你之前 做它 - 讓我們來運行的。 It didn't actually crash. 它實際上並沒有崩潰。 >> But if I change this, for instance, to be like 1,000, >> 但是,如果我改變這一狀況,為 例如,要像千, to make this really deliberate, let's see 使這真的 故意的,讓我們來看看 if we can get it to crash this time. 如果我們可以得到它的崩潰這個時候。 OK, it didn't crash. 好吧,它沒有崩潰。 How about 100,000? 如何約10萬? Let's remake it, and now rerun it. 讓我們來改造它,現在重新運行它。 OK. 行。 Phew. 唷。 All right. 好吧。 So apparently, again, these segments of memory, so to speak, 因此很明顯,同樣,這些 內存段,可以這麼說, are reasonably big, so we can get lucky again and again. 是相當大的,所以我們可以 一次又一次得到幸運。 But eventually, once you get ridiculous and really go far out on the screen, 但最終,一旦你得到可笑 真正炎等在屏幕上, you touch memory that really, really doesn't belong to you. 你觸摸記憶真的, 真的不屬於你。 >> But frankly, these kinds of bugs are going >> 但坦率地說,這些 種蟲子會 to be harder and harder to figure out on your own. 是難當 找出你自己的。 But thankfully, as programmers, we have tools that allow us to do this for us. 不過,值得慶幸的是,作為程序員,我們有 工具,使我們能夠做到這一點的我們。 So this is, perhaps, one of the ugliest programs, 因此,這是,也許是一 最醜的節目, even uglier than gdb's output. 比gdb的輸出,甚至醜陋。 But it always has a line or two that are super useful. 但它總有一條線或 2是超級有用。 >> Valgrind is a program that helps you not debug a program, per se, >> Valgrind是一個程序,可以幫助 你沒有調試一個程序,本身 but find memory-related problems, specifically. 但是發現內存相關 的問題,特別是。 It will automatically run your code for you and look for at least two things. 它會自動運行您的代碼 你看,至少兩件事情。 One, did you do something accidental like touch memory 一,你做了什麼 偶然像觸摸記憶 that didn't belong to you? 那不屬於你? It will help you find those cases. 這將幫助你找到這些情況。 >> And two, it will help you find something called >> 其二,它會幫助 你發現了一種叫做 memory leaks, which we have completely ignored, naively, 內存洩露,我們有 全然不顧,天真, for some time and blissfully. 一段時間和幸福地。 But it turns out, all this time, whenever 但事實證明,所有的 此時,每當 you've called getString in so many of our programs, 你所謂的getString在 我們這麼多的節目, you're asking the operating system for memory, 你問工作 系統記憶體, but you have any recollection of ever giving it 但你有什麼回憶 有史以來給它 back, doing unalloc, or free, as it's called. 回來了,做unalloc,或 免費的,因為它的調用。 No, because we've never asked you to do so. 沒有,因為我們從來沒有 要求你這樣做。 >> But all this time, the programs you've been writing in C >> 但所有這一次,程序 你一直在寫C語言 have been leaking memory, asking the operating 已經洩漏內存, 要求經營 system for more and more memory for strings and whatnot, 系統越來越 存儲字符串和諸如此類的東西, but never handing it back. 但從來沒有遞了回去。 And now this is a bit of a oversimplification, 而現在,這是一個有點 à簡單化的, but if you've ever run your Mac or your PC for quite some time, opening 但如果你曾經運行在Mac或 你的電腦很長一段時間,開 lots of programs, maybe closing programs, 大量的節目, 也許關閉程序, and even though your computer hasn't crashed, 而即使你的 電腦沒有死機, it's getting so much slower, as though it's really 它變得這麼慢得多, 好像真的 using a lot of memory or resources, even though, 使用大量的內存或 資源,即使, if you're not even touching the keyboard, 如果你不連 觸摸鍵盤, that could be-- but not always-- could be that the programs you're running 可能be--但不always--能 是因為你正在運行的程序 have themselves memory leaks. 有自己的內存洩漏。 And they keep asking the OS for more and more memory, but forgetting about it, 他們不斷地問操作系統的更多, 更多的內存,但忘記了它, not actually using it, but therefore taking memory away 實際上並不使用它,但 因此,服用內存離開 from other programs that might want it. 從可能希望它的其他程序。 So that's a common explanation. 所以這是一個常見的解釋。 Now here's where Valgrind's output is completely 現在,這裡的地方Valgrind的公司 輸出是完全 atrocious to those less and more comfortable alike. 殘暴的那些少 更舒適的一致好評。 But the interesting stuff is right up here. 但有趣 東西是正確的在這裡。 It is telling me an invalid write of size four happens in this program, 它告訴我一個無效的寫 大小4發生這個程序中, in particular, at line 21 of memory.c. 特別是,在memory.c的第21行。 >> If I go to line 21, hm, there indeed is an invalid write of size four. >> 如果我去到第21行,嗯,的確有 是大小為4的無效寫。 Why size four? 為什麼大小4? Well, this number-- and it could be anything-- is an int. 那麼,這number--它 可能是anything--是一個int。 So it's four bytes. 因此,這四個字節。 So I'm putting four bytes where they don't belong. 所以,我把四個字節 他們不屬於。 That's what Valgrind is actually telling me. 這就是Valgrind的 實際上是告訴我。 Moreover, it will also tell me, as we'll see, 此外,它也將 告訴我,因為我們將看到, as you run this in a future pset, if and when you've leaked memory, which indeed 當你運行這個在未來的PSET,如果和 當你的內存洩漏,這確實是 I have, because I've called malloc, but I haven't actually 我有,因為我打過電話 malloc的,但我並沒有實際 called, in this case, free, which we'll eventually see 叫,在這種情況下,自由 我們最終會看到 is the opposite of malloc. 是的malloc相反。 >> So now, I think, a final example. >> 所以,現在,我認為,最後一個例子。 So this one's a little more arcane, but it's perhaps 所以這一塊是一個有點多 晦澀難懂,但它也許是 the biggest reason to be careful with memory, 最大的原因 小心內存, and the reason that many programs and/or web servers, even to this day, 究其原因,很多節目 和/或Web服務器,甚至到今天, are taken over by bad guys somewhere on the internet who are somehow 被接管壞人的地方 在互聯網上誰是莫名其妙 sending bogus packets to your server trying to compromise your accounts, 發送偽造的數據包到服務器 試圖破壞您的賬戶, or take your data, or just generally take over a machine. 或者把你的數據,或只是 一般拿過來一台機器。 Buffer overflow, as the name suggests, means 緩衝區溢出,隨著 顧名思義,手段 overflowing not an int, but a buffer. 不溢出為int,而是一個緩衝區。 And a buffer is just a fancy way of saying it's a bunch of memory. 和緩衝僅僅是一個奇特的方式 的說這是一串記憶。 >> And indeed, I called a string before buffer, instead of s. >> 事實上,我叫一個字符串 前緩衝區,而不是S,。 Because if it's a buffer, like in the YouTube sense, 因為如果它是一個緩衝, 像在YouTube的意義, or any time you're watching a video, you might have seen the word buffering, 或者您正在觀看的視頻的任何時間, 你可能已經看到這個詞的緩衝, dot, dot, dot. 點,點,點。 It's incredibly annoying. 這是令人難以置信的煩人。 And that just means that your video player 而這僅僅意味著 您的視頻播放器 is trying to download lots of bytes, lots of bytes 試圖下載大量 字節,大量的字節 from a video from the internet. 從網上的視頻。 But it's slow, so it's trying to download a bunch of them 但它是緩慢的,所以它的嘗試 下載了一堆人 to fill a buffer, a container, so that you have enough bytes that it can then 填充緩衝器,一個容器,從而使 你有足夠的字節,它可以再 show you the video, without pausing constantly. 告訴你的視頻, 不停頓不斷。 But it turns out, you can have a buffer to this big. 但事實證明,你可以 有一個緩衝,以這個大。 But try to put this much data in it, and very bad things can happen. 但盡量把這麼多數據 微博,很糟糕的事情可能發生。 So for instance, let's look at this final teaser of an example. 因此,例如,讓我們來看看 一個例子的這個最終預告片。 This is another program that, at first glance, 這是另一種方案 即,乍一看, doesn't do anything super useful. 什麼都不做超級有用。 It's got a Main function that calls that function, f. 它有一個主要功能 調用該函數f。 And that function, f, up here, has a char array, called c, of size 12. 而且函數f,在這裡,有 一個char數組,稱為大小12℃,。 And then it's using this new function called strncpy. 然後它用這個 新的函數調用strncpy()函數。 >> It turns out that, with this simple, simple line of code, just two lines, >> 事實證明,這種簡單 代碼簡單的線條,只是兩條線, we have made my entire program, and therefore, my entire computer, 我們已經做了我的整個程序, 因此,我的整個電腦, and my user account, and my hard drive potentially vulnerable to anyone 我的用戶帳戶,我的硬盤 開車可能受到任何人 who knows and is good enough to run this program with a certain command line 誰知道,是不夠好,運行 這個節目帶有一定的命令行 argument. 的說法。 In other words, if this bad guy puts inside of argvargv[1] by typing 換句話說,如果這個壞傢伙 通過鍵入把argvargv [1]內 at the keyboard a very specially crafted string, not abc, 123, but essentially, 在鍵盤非常特製 字符串,而不是ABC,123,但本質上, binary symbols that represent executable code, a program that he or she wrote, 代表可執行的二進制符號 代碼,一個程序,他或她寫道: with this simple program, which is representative of thousands of programs 用這種簡單的方案,這是 代表的數以千計的節目 that are similarly vulnerable, daresay, he or she can ultimately delete all 這同樣是脆弱的,敢說, 他或她可以最終刪除所有 the files on my hard drive, get a blinking prompt so that he or she can 在我的硬盤驅動器中的文件,得到了 閃爍提示,以便他或她可以 type commands on their own, email all files to myself. 自己輸入命令, 電子郵件中的所有文件到自己。 Anything that I can do, he or she can do with this code. 什麼我可以做的,他 或她可以使用此代碼做。 >> We won't quite solve this yet. >> 我們不太解決這事。 And in fact, it's going to involve a little picture 而事實上,這將 涉及小圖片 like this, which we'll soon come to understand all the better. 這樣,我們將很快到來 理解就更好了。 But for today, let's end on what's, hopefully, a slightly more 但是今天,讓我們結束 什麼是有希望稍微 understandable XKCD joke, until we resume next time. 可以理解的XKCD笑話, 直到我們重新開始下一次。 All right. 好吧。 See you on Wednesday. 星期三見。 >> [MUSIC PLAYING] >> [音樂播放] >> SPEAKER: And now, deep thoughts, by Daven Farnham. >> 演講嘉賓:現在,深 思想,通過Daven法納姆。 Memory is like jumping into a pile of golden leaves on a Sunday afternoon. 記憶就像是跳進了一堆 金黃的樹葉在週日下午。 Wind blowing, tossing your hair-- oh, I miss the days when-- 風拂過,你折騰 hair--哦,我懷念的日子when-- >> [LAUGHTER] >> [笑]