[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]