[音乐播放] DAVID J.马兰:好吧,这是CS50 这是5周开始。 所以今天,坐垫底下, 你不会找到任何东西。 但最重要的,你应该找到这些, 我们欣赏的一点小小的心意 你把所有的工作 进入15游戏。 只要简单地除去小圈上 底部开始打 其余类。 所以记得或知道这个问题集 四,本周末出去, 涉及编写另一场比赛。 但是,这一次,它涉及到使用 实际的图形用户界面,而不是一个 文本界面,如 十五的游戏。 而本场比赛在于你前面, 如果你还没有见过这下, 看起来有点像这样的东西。 我要进入​​我的终端 在GDB窗口。 而且我要继续前进并运行 员工的解决方案,您可以访问 运行update 50后,像往常一样。 不过,我打算把它放入少许 秘密模式,一点点的复活节彩蛋, 所谓的上帝模式, 让上帝argv1。 我要按照我自己的方向, 在我自己的运行 问题设置目录。 所以,现在你看到一个完整的版本 的突围的比赛。 其实,这是没有手模式。 因此,它实际上是 - 叫绝尽管你可能会对 - 很容易实现上帝模式 突围,不像十五的游戏, 一些你可能已经解决 黑客版。 在突围中,只要在上帝 模式简单地做什么, 直观地与桨? 只要使它等于不管 水平位置的球。 所以只要你做到这一点步调一致 ,球移动这个游戏会 永远,永远,永远错过了球 你会每次都赢。 但在本周的黑客版 有以上只是上帝模式。 有一些其他功能。 其中,激光器。 所以,如果你真的不耐烦 可以击落砖开始 和其他几个人。 而对于那些你谁想要 校准标准与黑客 版,我可以看到,本周的 黑客版故意是一个 更可行一点,也就是说,不是神 模式是与游戏的十五。 所以,如果你正在寻找一个舒展和 你正在寻找一些额外的乐趣 如果感兴趣的功能做潜水。 现在更实际,让我点 一件事。 GDB,有些人可能还没有 亲自感动,这是很好的。 但现在是真正的时间来习惯 这和舒适的使用这个工具 因为它会让你的生活 更容易,真正做到。 每罗布GDB的一对夫妇的讲座 数周前,记得 ,GDB调试器。 这是一个工具,可以让你运行你的 程序,但运行它一步一步,线 行,让你可以闲逛, 所以,你看到的事情发生,所以 您可以打印出来 变量的值。 总之,它给了你这么多 功率比printDef。 诚然,现在的界面 是相当神秘。 黑色和白色的文本界面 在大多数情况下。 命令有些艰难 记得在第一。 但是,即使它可能需要你的一半 一个小时,一个小时,把前期 投资的时间把它,相信我。 当然学期的结束,这将节省 你一个数量级以上 时间比。 所以早在本周长驱直入 在突围方面,知道你 能做到这一点,只要你有 分配代码或您自己的代码 在建您的Pst4目录。 要知道,你可以运行gdb。/突破。 这将开辟 这样的窗口。 让我给自己更多 一个终端窗口。 然后呢,我要继续前进 做的,它的不只是运行它。 我要首先设置了一个破发点 召回,它允许你暂停 在一个特定的地方执行。 只是为了简单起见,我要去 只需键入打破行一 头号。 实际上让我重新打开此窗口 因为它才获得了 有一点小。 所以现在,我要在这里做什么 如果我打开终端窗口。 来吧,我们去那里。 所以,现在如果我回去到Dropbox,Pst4 运行gdb。/突破进入,请注意 我要打破一个设置 一个破发点,线一条。 现在我要去 运行前方和类型。 而当我这样做,注意什么 似乎发生。 有没有弹出。 有没有图形 用户界面。 但是,这是可以理解的,因为我 字面上线在我的计划之一。 注意到我快进, 特别是现在到62,因为所有的 在这个文件的顶部的东西是 像注释和常量和 现在的无趣的东西。 所以我现在的主要内, 看起来,在第62行。 而这仅仅是分配 代码,召回。 如果我开这件事,同样, 进入我的下拉框成Pst4目录, 到breakout.c。 如果我向下滚动下来,下来, 并让我继续前进,打开 我的行号。 我会看到什么,如果我向下滚动到 62号线,是完全行 我们已经暂停。 因此,这条线在这里,62岁, 我们是。 所以,现在在GDB,如果我先走,然后键入 现在下,进入它要 执行这条线。 瞧,我们有 所谓的克窗口。 如果什么GWindow不熟悉 ,不用担心。 该规范将为您介绍它,因为 以及大量的演练视频 嵌入在规范中。 但现在让我们做一个 更有趣一点。 让我移动这个窗口 一边一点点。 让我一点窗户 更大,所以我可以看到更多。 现在让我继续 和再下一步要做。 而且有我的砖。 如果我再接下来键入 现在我看到球。 如果我再接下来键入 现在我明白了桨。 幸运的是,这gedit中不 通过展示我真正合作 我想要的一切。 但现在如果我再下一步做, 再接下来,我只是 声明一些变量。 我可以打印任何一个 这些家伙。 打印砖,版画的生活。 现在如果我继续做 接下来,请注意,我会 里面的这个循环。 但是代码执行 正是因为我的期望。 所以,当我打这个功能,等待 按一下,它会做 它的字面。 所以,我似乎已经失去了控制 在节目。 GDB是不给我另一个提示。 但不用担心。 转到我的游戏,点击的地方。 瞧,现在进行到第86行。 再次,它是无价的,最终, 调试问题。 因为你可以从字面上步骤通过 你的代码,打印多东西出来, 多少,等等。 但现在,这些工具本身 应该让你很远。 因此,我们,当然,考虑看看 现在显卡,一下子。 现在我们的世界变得有点 更有趣。 你知道,或许,从一些 我们这些在线视频 短裤,你已经看 习题集的一部分。 他们已经出手,故意 以白色背景。 他们中的一些教学 图纸上的某些文本研究员 屏幕覆盖 上侧。 不过,当然,这还不是全部, 在现实世界中有趣。 这仅仅是一个与报告厅 白色的大屏幕和背景。 我们惊人的生产队排序 让一切看上去很美 通过裁剪后的事实 或覆盖任何东西 我们做什么或不想要的。 现在只是为了激励这个星期, 真的,你可以去,最终, 计算机科学。 问题后,不只是设置了四个。 但之后其他课程或整个 课程是惊人的,你可以 这几天而言, 尤其是在图形。 你们当中有些人可能已经看到了这 网上四处流淌。 但我想我会告诉你,只是一个 两分钟,一窥究竟 计算机技术和CGI 计算机图形可以做这些天 熟悉的歌曲 也许电影。 [MUSIC - LANA DEL射线, “年轻和美丽] 扬声器1:这只是一点点 惊人的,也许,只是如何 无处不在 - [掌声] 扬声器1:我刚下载了它。 但它真的很神奇,我想,只要 无所不在的软件和代码, 真的是这样的工具。 所以这是一个品味的方向 在其中,你可以走了。 哦,没有更多的电器。 嗯,这实际上是悲惨的时机 点我只是试图让。 好吧,让我们推出 再次融合。 稍后提醒我。 没事了,你应该有一个 顺便说一句,如果你确实得到了电子邮件 类似的通知。 好吧,所以记得,上周 我们开始剥离回 后来被称为串。 字符串回忆起一个数据类型 宣派CS50库。 它的一部分训练轮 现在将开始起飞。 这是一个有用的概念,早期。 但现在它要得到更多 有趣和更强大 实际看到的引擎盖下, 一个字符串就是什么,我们说的吗? 是啊,所以这是一个所谓的char *。 *表示有 涉及某种形式的地址。 因此,当你说你的char *仅仅意味着 一个变量,其数据类型是一个 指针现在。 事实上,有星级 只是意味着你声明 所谓的指针。 该指针是怎么回事显然 存储的地址, 当然,一个字符。 现在为什么不这样做有意义吗? 那么,什么是一个字符串 引擎盖下? 那么,未来一段时间,我们一直在说 引擎盖下是一个字符串 只是H-E-L-L-ø,例如。 但我们已经谈到这是 即,本质上,一个数组。 阵列,然后看起来有点 类似这样的,与这些 咬了一口。 然后我们说,有 一些特别的东西,回到这里, 反斜线0或null终止。 所以这一切的时候,在这里 一个字符串。 不过说真的,一串串 实际上是一个地址。 和地址,如我们所看到的,往往是 按照惯例用0x前缀。 0X表示什么? 有谁知道? 因此,它只是表示十六进制。 所以,你可能还记得,实际上,从PST 1,我相信,一个热身 问题居然问 十六进制表示法中除了 二进制和十进制。 这里的动机是 与十六进制你有16 数字在您的处置。 0,1,2,3,4,5,6,7,8,9,其次 由A,B,C,D,E,F。 如果算上所有这些向上, 你得到了总共16个。 因此,这是在对比 小数,其中有10个 数字0到9。 它的对比度与二进制 我们只是0和1。 但在年底的一天,你可以 表示相同的数字,但 有所不同。 和十六进制是常见的,因为 事实证明 - 我们将看到这一点 后面的课程 - 即使当我们得到 web编程的背景下, HTML和颜色代码, 十六进制是好的。 因为每一个数字,事实证明, 代表完美四位。 因此,它只是一种很好的线 因为我们最终会看到。 所以这可能是Ox123或东西 这样,表示地址123 里面有我的地方 计算机的内存。 不过,当然,出现了一些问题 因为这一基本 实现。 记得我把刺在 实现这样的功能 - 比较破折号0 C点上周 即使它看起来就像是 没错,它根本不比较 两个字符串正确。 我扔掉的主,我已经抛出 远的意见只是集中在上 代码的兴趣。 ,它是红色的,因为它是越野车。 什么原因呢? 嗯,上方还有,当我宣布 一个字符串,什么是真的 引擎盖下? 那么,就让我走了过来的 此处的画面和借鉴。 所以,我再次宣布, 字符串s的GetString。 所以我要继续前进,现在 画为它到底是什么。 这将是一个正方形。 我要去要求 那是32位。 至少它通常是, 至少在CS50 很多计算机的器具。 我会打电话给它s。 但是,现在还记得我们 称为GetString的。 所以GetString的回报, 当然,一个字符串。 如果H-E-L-L-Ø用户类型进入 获取返回字符串hello。 而该字符串,正如我们刚才所说,结束 某处在您的计算机的内存 在最后一个反斜杠0。 我会得出这样的像数组 - 连续的字符块 - 它实际上是。 而现在,则由GetString引发什么 实际上返回? 有什么的GetString返回 所有这段时间呢? 好吧,我们说,在几周之前, 它返回一个字符串。 但更多的技术上的,这是什么 显然则由GetString引发返回? 观众:一个地址。 扬声器1:一个地址。 具体来说,它返回的地址 第一口,不​​管它是什么。 我只是不停地用一,二,三 因为它的方便。 返回地址的第一个 字符串中的字符。 我们上周说, 是足够的。 因为我们总是可以找出其中 仅仅通过结束的字符串 遍历它,也许,与为 循环或while循环或类似的东西 ,只是在寻找“反斜线0”, 特殊定点字符。 然后我们知道该字符串 的长度恰好是 - 在这种情况下 - 五。 因此,技术上的GetString做什么 是在这种情况下,它返回Ox123。 技术上然后发生了什么 我们存储,里面的s,Ox123。 在一天结束时,尽管这 是新的概念,指针,他们 只是变量。 但他们碰巧存储位 共同表示一个地址。 所以技术上都得到 在s中存储的是Ox123。 但我们作为人类 - 包括今天起 - 真的不会在意,通常, 实际地址是什么 一些大块的内存。 这只是低水平的细节 智力有趣。 所以我打算撤消此。 ,而是更多的高层次,只是说 当我们在谈论指针 我要吸引更多 用户友好的箭头,传达 同样的想法和摘要走 什么实际的详情 基础地址。 现在,如果我们回去的代码, 上周发生,如果我们有字符串t 等于则由GetString引发? 好吧,如果我再次类型打招呼 这次我会得到 另一块内存。 H-E-L-L-O反斜线0。 但是,因为我要求则由GetString引发 第二次 - 我知道这看着 GetString的源代码 - 即使 虽然这是巧合,打招呼 输入两次,GetString的是不 要尝试优化 和聪明。 只是要得到另一块 从计算机中的存储器,这是 要在另一个地址。 让我们任意只是说456。 然后它是什么会回来? 这将返回456 并将其存储在t。 那么,什么是真的,在 左侧是我有另一块 内存,通常是32位。 在那里要去Ox456。 不过,我没有兴趣在这些 特殊的数字了。 我只是抽象 绘制箭头。 所以这是现在一种新的解释。 但它是完全相同的想法 发生这一切的时候。 等原因,那么,这首 版本比较的是越野车, 上周是为什么呢? 当你这样做,如果s等于等于 什么是你真正的吨 引擎盖下比较? 你的地址进行比较。 只是直观,清晰,Ox123 不会等于Ox456。 这些数字,那些位 只是不同而已。 所以一致,上周说 你键入不同的事情,即使 话逐字相同。 因此,我们解决这个问题。 通俗地说,什么是修复? 观众:使用功能。 扬声器1:使用功能。 明星们肯定参与, 但使用功能做什么呢? 观众:要比较字符串。 扬声器1:比较字符串。 所以这里的根本问题是 我只是考虑 质量被定义的字符串 他们的地址相比较。 很显然,这只是愚蠢的现在一次 你明白这是怎么回事 引擎盖下。 要真正比较字符串,看是否 他们是平等的,一个人的方式 会考虑两个字符串是否相等 我们需要对它们进行比较字符 对于字符。 现在我可以做 这很繁琐。 但是,我们亲热 使用for循环。 而只比较Ş支架 我对T支架í。 Ş支架I加1对T支架 i加1,依此类推,里面 某种循环。 如果我发现任何两个字符 不同,或者如果我意识到,哦,S 小于t或长于t 我可以马上说是假的, 他们是不一样的。 但如果我通过s和t说 相同的,相同的,相同的,相同的,同样,年底 这两个字符串,我可以说, 真的,他们都是平等的。 那么,令人欣慰的是,几年前,有人 为我们写的代码。 他们把它称为StrComp 字符串比较。 即使它是一个小柜台 直观,StrComp返回0,如果这些 两个字符串中,s和t是相同的。 但是,如果返回负值 应该是之前按字母顺序或 它应该是正值,如果 后T字母顺序排列。 所以,如果你要排序的东西, StrComp是有用的。 因为它不只是说 yes或no,等于或不。 它给你一个订货感 喜欢字典威力。 所以StrComp,S逗号T等于 等于0,则表示 字符串是真正的平等。 因为谁写了这个功能 几年前大概使用了一个for循环 或一个while循环或类似的东西 再次,整合过的字符 一遍又一遍。 但这里出现问题2。 这是copy0.c。 和两个红色 因为它是有缺陷的。 我们做了什么? 嗯,首先我叫则由GetString引发。 我和存储在s的返回值。 所以这是相当多的相同 这个图片的上部。 但之后呢? 好吧,让我继续前进,摆脱 一大堆。 我们的地方,我们只是时间会倒转 有,这是现在一致 线那里。 我检查。 如果s等于等于0。 现在,快速侧面说明,当 可能的GetString返回0? 有没有足够的内存。 对吗? 这是罕见的,这是将要发生, 当然这是一个计算机 有数百兆 甚至音乐会的RAM。 但也有可能,在理论上,返回 0,特别是如果 用户不配合。 有办法假装像你有没有 输入任何东西和诀窍 返回到则由GetString引发 0有效。 因此,它要检查。 因为如果你开始 已经得到的,分割故障 - 这可能是一个源 有些无奈 - 这些结果几乎总是 内存相关的错误。 不知怎的,你搞砸了,对于一个 指针,即使你没有意识到 有一个指针。 所以,你可能诱发分割 早在第一个星期使用故障 像一个循环或while 循环和阵列走得太远的 过去的一些阵列的边界 宣布,在本周二 尤其如此。 你可能已经做了,即使问题 设置四个与突围。 即使你可能从来没有见过 任何恒星分布代码 突围,事实证明,那些GRect 和GOval和其他这样的事情, 其实这些都是指针 引擎盖下。 但是,斯坦福大学,像我们这样的,排序的皮革 至少详细的库 的目的,就像我们做 字符串和char *。 但GRect GOval所有这些 你们的事情或将使用 这个星期都少不了 内存地址。 你只是不知道这一点。 所以这是不奇怪的话,也许, 你可能会绊倒一些 段故障。 但是,什么是有趣的, 如果我们检查后我们做 字符串t得到s。 好吧,让我申报吨。 我打算把它画一个正方形, 32位,它吨。 然后我要做的事情,得到s。 那么,是什么意思呢? 嗯,这是一个有点很难想象 关于它的想象明智的。 但是让我们想想 里面的x是什么? 这里面变量字面上什么? 价值Ox123。 所以当我说字符串t得到s,这只是 字面意思是取数 在s,这是Ox123,并把它Ox123。 或形象,如果我有点抽象 远离细节,它有 从字面上做效果 这一点。 所以,现在,回想起上周 我们进行资本主义T.我 Ť支架0。 那么,T支架0,即使它是一个 指针,你可以把它仿佛 它是一个数组,用方形 支架符号。 那么,是T支架0? 那么,它的h。 因此,当我们使用这行代码, 两个上,是C type.h中的 头文件,这就是 它的声明。 你把握H.但 当然,这是完全相同的h上 s的内部,可以这么说。 所以现在你已经改变或 资本化的原件和 所谓的副本。 因为你没有做一个副本 的方式,一个人会希望它是。 那么,什么是这里的修复, 在上周copy1.c? 功能,所以实际上,我们可以 复制字符串。 从根本上说,我们需要 做以复制字符串? 那么,在我这里这个绿色版 要做到这一点相当低的水平。 实际上有功能 他们可以帮助这一点。 但是最基本的,而最 熟悉的,至少会很快 我们所熟悉的,是下面的 - 所以在第一行 现在代码在绿色。 我刚刚改写的char * s作为。 有没有功能 区别。 我只是扔掉CS50库 我打电话是什么,它​​是一个char *。 现在,点,点,点,因为有 这不是一些错误检查 有趣的念叨。 所以,现在t的声明。 它也是一个char *。 所以我画了一个小广场上 屏幕上像前。 但在右侧时,malloc 我们说的是内存分配。 因此,分配一定的内存块。 和我们实际上做了多少字节 要分配,它似乎? 嗯,字符串的长度为s。 所以,如果要打招呼, 是五。 我们会说:H-E-L-L-O。 因此,5个字节。 但是,再加上1,为什么? 0字符。 如果我们不留有余地,这家伙我们 可能无意中造成这样的局面 字符串是H-E-L-L-O。 那么下一次的GetString 叫我输入,例如, 戴维,D-α-v型的i-ð时,计算机会 认为s是 h-e在升升 - 邻-D-α-v型的i-D因为有 没有打破这些单词之间。 因此,我们需要休息。 所以,我们不希望五。 我们需要6个字节。 和字节我说。 但它是真的时大小字符。 技术上char是几乎 始终是一个单字节。 但是,只是为了让我们的代码便携, 可以这么说,所以它的工作原理 不同的计算机上,即使他们可能 下方的有所不同 油烟机,我要笼统 说尺寸的字符,所以 我的代码总是工作。 我没有重新编译它只是 因为我的计算机升级或使用 一些不同的平台。 所以我已经有了6倍的大小 一个字符,这恰好是1。 因此,这意味着的malloc 给我六个月字节。 ,实际上做的是什么? 好吧,让我回滚时间在这里 我们所处的这个故事。 所以,如果我回到这里,我已经声明 一个char *名为t。 我现在已经被称为6字节的malloc。 现在我要吸引那些六 就像字节数组同期。 但其实我不知道什么是 这个数组里面。 如果你分配内存事实证明, 你可以不相信有一些 已知值。 它可能已被使用的东西 否则,其他的一些功能,其他一些 你写的代码行。 所以,我们一般会调用这些垃圾 价值和借鉴他们,也许, 问号,只是表明我们 不知道什么是实际存在的。 这没什么大不了的,只要我们 有足够的智慧来覆盖这些 垃圾值以数字或 我们关心的字符。 因此,在这种情况下,我该怎么办? 好吧,我行代码 接下来,我有四个。 INT I得到0,n变 字符串s的长度。 因此,一个熟悉的for循环。 I小于或等于n, 这通常是上述。 但是,这一次它是经过深思熟虑的。 我+ +,然后我只是做 吨支架我得到s。 因为我的照片看起来像这样 储存在这一刻,是 ,随机的内存块的地址 它的值是未知的。 但只要我做T支架 0,让我在这里。 什么最终会被绘制在那里? 我们最终把ħ。 ,因为这是在s支架0。 然后同样的事情 E,和l,和l和o。 N,为什么我去通过 一个等于n? 由于“0”字符。 所以只要是明确的,那么,如果我真的 清除这些垃圾 值,然后绘制 我所期望的,这是支架1,2, 3,4,加尾随 新的字符。 所以,如果我们现在继续过去的点, 点,点在这条正确的版本 及资本化支架0我想, 当然,把握这一点 家伙在这里,从概念上讲, 最终的目标。 所以这是所有的指针。 而你一直在使用他们周 现在在字符串的上下文中。 但引擎盖下他们 更复杂一点。 但如果你认为他们在这 图文并茂的形式,我建议他们 可能不是所有的可怕,因为他们 可能先乍一看, 尤其是这种新的语法。 如有任何问题上的指针, 字符串或字符? 是吗? 观众:你能回去 [听不清]? 扬声器1:当然。 观众:那么,为什么你最后的 行了,你没有一个* T线 行中的A * S? 难道你不具有参考 - 扬声器1:啊,一个很好的问题。 为什么不我有一个* t和A * S? 因为简单地说,上周,像在我们的 交换功能,我没有说,当 你已经有了一个指针的手段 你去那里,因为我们没有 身体在舞台上,实际 使用星算。 事实证明,这个方括号 符号是什么,我们会打电话给句法 糖,这仅仅是一个性感的方式 说这是速记符号 正是你所描述的。 但它更直观一点。 决策的风险,这似乎更 复杂,比它需要的是, 这里到底发生了什么 - 如果我说*吨,这意味着去 在t存储的地址。 从字面上看,如果T是存储 使得h的地址 最初,* T手段去这里。 现在,吨支架0是什么意思? 完全相同的事情。 这只是一个对用户来说更加 友好的写。 但我还没有完成。 我不能只是说* T *秒获得。 因为我会做什么呢? 我把H,H,H,H,H 在整个事情。 对吗? 由于* t是在t的地址。 但是,我们是在一个循环内。 什么样的价值,我在递增, 当然,在每次迭代中吗? (一) 但是,有一个机会 在这里,对不对? 尽管这种感觉就像它变得 更复杂一点 方括号表示法比 我们已经用了一段时间 - 让我撤消我的H有变化 - 即使是现在开始有点 神奇的是,基本的想法,如果* T 这里指的* t是刚刚 去t的地址。 但是,什么是在t的地址? 我们一直使用的号码? 像Ox456,让带回来 只是就事论事。 好吧,如果我想要得到电子 吨字符串,我只是想归想, 从本质上讲,456。 或者更确切地说,457。 我只需要添加一个。 但我可以做到这一点,对不对? 因为T,即使我把图纸 现在作为一个箭头,它只是一个 号,Ox456。 而如果我添加一个,或多个 一般而言,如果我加我,我可以 实际上,正是我想要的。 所以,如果我真的这样做 - 这就是现在被称为 指针运算 - 我可以删除这一行。 这是,坦率地说,我觉得更清晰, 对用户来说更加友好的阅读。 但是,这是不正确的。 现在这行代码使用 指针的算术运算。 说去 地址如下 - 无论吨开始,这 再加上我是,最初 为0,这是伟大的。 因为这意味着吨的开始 加1,加2,加3,依此类推。 和相同的处理为s。 所以语法糖。 但是,了解究竟发生了什么事情 引擎盖下,我认为, 本身实际上是有用。 因为这意味着现在有没有 更魔法 引擎盖下。 不会多 我们可以剥离备份你的层。 这是c。 这是编程。 真是个好问题。 所有的权利,所以这是那个马车 我指的是早期的程序。 交换是有缺陷的。 如果没有似乎工作。 回想一下,就像牛奶和 橙汁 - 我开始 喝今天的示范。 因此,正如橙汁和 牛奶,我们也必须使用 临时变量,TMP,举行 暂时这样,我们便可以 改变它的值,然后更新B。 但是这个功能,我们说,这 程序中,此功能 写的是错的,有缺陷的,为什么呢? 是吗? 观众:[听不清]。 扬声器1:没错,当 你叫掉期 - 或者更一般地,当你 调用任何功能最 - 如果该函数的参数 原始的,可以这么说,整数和字符 双打和花车,万物而不 星星,你是通过在副本 的说法。 因此,如果x为1,y为2,将 1和b为2。 但他们要去不同的块 位,不同的块 内存发生存储 相同的值。 因此,这段代码是超​​级完美 在交换a和b。 这是没有什么好交换 - 在上周的例子 - x和y。 这还是因为同样的原因,他们是 在错误的范围内。 现在,我们怎么去解决这个? 我们不得不做出的功能 看起来有点丑陋。 但是还要考虑什么 这也就意味着。 而实际上,让我的一致性, 改变的一件事,所以这是相同的 我们只是做了什么。 正如我上周提到的,它不会 无论身在何处。 事实上,通常你会放 星级旁边的变量名。 但我认为这将是更容易一些 旁边的考虑* 这意味着它的数据类型是一个指针 在这种情况下,一个int。 所以我在这里做什么? 我说不要给我一个int 其次另一个诠释, 称他们为a和b。 给我一个int的地址。 给我地址的另一种诠释。 调用这些地址a和b。 然后使用*符号下降 下面,每个地址 根据需要,以得到 或设置其价值。 但这里有一个例外。 为什么我不会有* TMP旁边? 为什么我不能做到这一点,例如? 这感觉就像我应该全力以赴 和纠正整个事情。 是吗? 观众:[听不清]。 扬声器1:我还没有宣布 tmp作为一个字符串。 因此,这将声明,在这种情况下, 一个tmp目录是一个int的地址。 但是,这不是我想要的那种, 一对夫妇的原因。 观众:你不想来交换他们。 扬声器1:没错,我不想要交换 任何与TMP。 tmp是刚 本周一的东西。 所有我想要的是一个变量 存储一些数字。 我什至不关心地址 在这一刻。 我只需要32位或 因此存储一个int。 我要把这32位 无论是不是在,可以这么说,但 处于什么,只是为了更精确。 因为如果是一个地址,一个表示 去那里,并获得价值1。 例如,在上周的例子 或在b的情况下,得到的价值2。 所以,到底发生了什么? 让我画一幅画,在这里,将 只梳理除了今天的一部分。 但是,这将继续出现 相当长的一段时间。 ,我要求,这就是您的电脑 当你运行一个内存看起来像 程序,任何程序。 当你运行一个程序在最高层 您的计算机的RAM - 所以想到 这个矩形,真正实现了,因为你的 计算机的RAM或内存,所有101 全2亿亿字节, 字节,两个千兆字节的, 无论你有, 让我们绘制一个矩形。 我要求,当你运行一个程序 如Microsoft Word或Chrome 或类似的东西,的位 微软,谷歌写道 - 在这些程序的案件 - 被加载到您的计算机的内存 在那里他们可以执行 迅速送入CPU, 是计算机大脑。 谭它们存储非常 你的程序,可以这么说。 换言之,如果这是一个块的 内存,当你双击 微软的Word,位来 关闭硬盘驱动器。 他们得到加载到RAM中。 我们要赶路他们在最高层 这个矩形的概念。 好吧,剩下的是你的记忆 用于不同的事情。 在最顶端,你看到初始化 数据和未初始化的数据。 这样做的,在大多数情况下, 常量或全局变量 有值。 但那些其他时间。 然后你有堆, 我们会回来的。 但在底部则是部分 尤其是现在有密切关系。 这是所谓的堆栈。 所以,就像在任何D厅 大学校园,你有那些托盘 只是堆放在彼此顶部上 你可以把食物和诸如此类的东西。 在计算机系统中的堆栈 是非常相似的。 除而托盘,我们使用 食堂,当然是 随身携带的东西托盘 或框架 - 因为我们会打电话给他们 - 在计算机的 存储器是用来存放 变量和值。 那么真正的推移 引擎盖下? 好吧,让我翻转 这里的画面。 而让刚上的重点 片刻的底部的一部分。 如果这是我的底部 电脑的记忆体,它原来的时候我 调用函数主 - 发生的事情,坦率地说, 自动为我 - 我得到一个内存块 我的内存的底部可以这么说。 这是主要的 局部变量去。 这是argc和argv也许 走,和我的任何变量 主要内申报。 他们最终在底部 我的电脑的RAM。 现在,假设主要的电话功能 像掉,像它上周? 好吧,我们基本上是把一个新的托盘, 新的框架,到我的内存块。 我要形容这是 属于交换功能。 现在里面有什么交换? 嗯,根据上周的节目 我们刚才看到的一段摘录, 交换的框架内,或掉期 托盘,有哪些变量? 那么,a和b。 因为那是其本地的参数, 加上第三,TMP。 所以,说真的,我可以得出这样的 一个更干净一点。 让我继续前进,撤消标签。 我要求你知道是什么吗? 一个很可能会在这里结束了。 B是在这里要结束了。 和TMP在这里要结束了。 现在,顺序可能 有点不同。 但是,这是概念上的想法。 只是统称,这是什么 我们会打电话给交换的框架,或 餐饮大厅托盘。 同样处理主要。 但我不会重绘。 但是,这其中argc和argv和任何 等局部变量x和y 可能。 所以,现在考虑到底发生了什么 当你调用掉。 当你调用swap,执行这样的代码 这一点,你正在传递中,在 越野车的版本,a和b; 作为x和y的副本。 所以,如果我现在得出这样的 在屏幕上 - 得到得到更好的产品 - 这样的故事,我告诉我自己 在这个马车版本,当我们 调用交换传递字面上a和b 整数,到底发生了什么? 那么,这到底发生了什么。 让我继续前进,只是撤消 这里明确了一些空间。 所以这是我的电脑的内存。 所以,如果我有,例如 - 居然让这样来做 - 如果这是我要求的x,存储 就像上周的值为1。 这是Y,存储的价值 就像上周。 这是主要的,当我打电话交换, 从而给自己访问和 b和TMP,我要去声称 这是一个,这是1。 这是b。 这是2。 这就是所谓的TMP。 最初,它有一些垃圾值 直到我真正存储在一个 这是1。 然后,我去动手改变 一个是什么? B的值。 所以现在我这里有两个。 然后我们说,B得到TMP。 同样,就像进行仔细的检查,第三 这里的代码很简单,就是 一,B得到TMP。 所以最后,我该怎么办? 我继续前进,变动b是什么 tmp的值,也就是1。 我不碰TMP。 但是,现在的问题是尽快交换 的回报,因为它的不移交 备份有一定的价值,不归路 声明中明确。 实际上发生了什么? 嗯,基本上这一切的记忆 - OK,显然橡皮擦喜欢 只用一根手指在一个时间 - 就这样消失。 现在,在现实中,它不是 去任何地方。 但是,你可以把它想象 现在为问号。 因为它不再 实际使用。 并没有什么做这些值。 因此,在的情况下,绿色版的 这段代码,而不是什么是 传递到交换? 所以解决。 因此,x的地址和 y的地址。 因此,如果我们重新讲述这个故事的最后一 时间,其实我画再次交换, 但与指针,这是一个,这 B,这是TMP,是什么 实际上存储在这个绿色 我通过我的代码版本 在地址? 这将是一个指向x的指针。 所以,我可以画一个箭头。 但是,让我们使用相同的任意 如前。 比方说,这是 像Ox123。 这是怎么回事Ox127,因为 这四个字节,因为它是一个 INT,所以Ox127。 再次,我采取了一些自由 数字。 他们会比他们小得多 实际上是在不同的顺序。 但是,这是怎样的画面 现在不同了。 但是当我使用这个绿色的代码 我INT TMP * A。 *一种手段,做到以下几点,采取 解决在去 这是1。 这就是我然后把tmp中。 同时,在下一行代码 在这里,一个得到b,是什么意思呢? 那么,*,所以要在这里得到* B, 这意味着去那里。 这意味着把那里的价值。 最后,最后一行代码 简单地说* B得到TMP。 所以B说去那里,覆盖它 tmp的,在这种情况下,将 再次,1。 这就是为什么绿色版 我们的代码工作,而红色 版本从来没有。 这一切都只是归结到如何 内存管理,并在它的 实际上放置在您的 计算机的RAM。 现在来看,这是一个的事 堆栈被用于。 布局上的问题? 指针? 或掉期? 所有的权利,这样的malloc,召回, 做这样的事情。 这是一个超级简单的例子。 这是一个宾基 向我们介绍,虽然相当 很快,在末级。 该死,我们又来了。 所以记得,这是例子 宾基向我们介绍,尽管 有些快速末级。 在这里,我们真正使用的malloc 第二次。 因为我们第一次用它来 创造足够的RAM,分配足够的RAM 存储字符串。 这一次宾基保持简单。 因此,它是只存储 一个int,显然。 这是完全正常的。 这是一个有点怪异,坦率地说, 使用malloc来分配一个int。 但有一点是尼克的黏土动画 真的只是讲什么样的故事 发生或不会发生在 你虐待内存。 因此,在这种情况下,本程序 做了几件事。 这里在第一种情况下,它声明 一个指向名为x为int类型。 然后声明一个指针 称为y为一个int。 然后,它存储在x,什么? 现在别人。 什么被存储在x 第三行这个程序吗? 观众:[听不清]。 扬声器1:嗯,不太 字节,每说。 现在更精确。 被存储在x什么? 一个地址,我想我听到了。 那么,是什么的malloc返回? 行为上的malloc分配 一块内存。 但它是如何给你访问它? 它返回什么? 第一个字节的地址 在内存块。 现在,这是超级简单。 这只是一个字节,这意味着 解决我们要的是 整个事情的地址。 因此,存储在x,那么,地址是 该内存块。 同时,接下来会发生什么? 因此,实际上,让我们继续前进, 绘制出真正的快。 因此,如果我们去到屏幕 我们玩了这一点* X和int * Y 打算做什么我? 我要求它只是打算做 这样的事情,并称之为x, 这Ÿ。 同时,第三行代码 要分配一个int的大小, 这恰好是 - 对不起,如果我说 前一个,我的意思是一个int - 一个典型的计算机上的四个字节。 至少与CS50器具。 所以,这是怎么回事分配 它,谁知道? 某处在这里。 而这在某些存储 地址牛,谁知道? 但是,这是怎么回事返回 是该地址。 但是,我们会得出这样的形象 只是这样的箭头。 现在,在下一行* x变42。 * X是什么意思通俗地说? 只是去那里。 进入到该地址。 或者换句话说,按照 箭头,并有42把。 但是坏事发生 宾基,对不对? 回想一下,行五在这里,* Y获取 13日,确实是一个不吉利的数字, 做了什么,对我们? 那么,* y表示去那里。 嗯,这还没有得到 值,对不对? 代码没有y为 初始化任何东西。 我们照了X被初始化 一个地址。 但Y被宣布往上顶。 但随后一个分号,没有价值 实际上是把它。 所以这是公平地调用这个 垃圾值。 谁知道那里有什么? 这是残存使用的位 以前的一些行代码 我的计划。 所以,如果我说去那里,这是什么样子, 我不知道这个箭头 要结束了。 这时候你通常 得到分割故障。 如果你不小心取消引用,所以 说话,还是去这不是一个地址 实际上是一个合法的地址, 不好的事情发生。 这到底发生了什么 宾基认为。 所以记得尼克的故事 这里讲的是同样的想法什么 我画的错觉 粉笔在黑板上板。 X和Y宣布。 然后我们分配的大小 一个int,并把它保存在x。 然后我们所做的下一行* X。 这是尼克的魔杖 提领。 这把42在存储器 指出由x。 但是,这是东西 去可怕的错误。 对吗? 试图取消引用Ÿ。 但Y有一些虚假的价值,对不对? 在左下方即箭头 角落里,是不是 其实都指向任何东西。 这是一种做什么,我 在这里做的在黑板上。 如此糟糕的事情发生,分割 故障时,或宾基故障,在这种情况下。 但是,如果我们再解决,通过做x 得到Ÿ的故事是如何变化的呢? 嗯,如果我做X得到Y,这是 同样有效的话说 不管这是牛的东西 这里是相同的, 牛年的东西。 或者形象,我们将绘制一个箭头。 所以在这里宾基板, 的下一行 代码* y表示去那里。 哪里有? 这意味着在这里。 而当我们更新到13 它只是涉及到要和 写13现在在这里。 因此,也许不完全 乍一看简单。 但总括来说,并使用相同的行话 宾基是用在这里,所以 前两个分配的指针, x和y,但不是指针对象。 指针对象是不是一个 通常使用的术语。 但指针绝对是。 但究竟是什么原因被指向 在宾基命名。 这下一行,当然 分配一个int pointee的。 所以一大块内存 - 因为我吸引了 右手侧 - 集 x等于指向它。 这解引用x到存储42 内存,它的指向。 然后,当然,这 是一件坏事。 因为Y并不是指向 任何东西。 这修复它。 因此,这仍是错误的程序。 只是因为我们正在吹遍 代码一行行,并说,很不错哦, 让它崩溃。 这是一件坏事。 赔率是程序只是要 完全中止在该行。 但是,如果你要删除坠毁 排队,取而代之的是与过去两年 线等也有你分配 - 使用指针赋值 - γ 指向x作为点t。 然后你取 y在一个非常安全的方式。 那么,这给我们吗? 嗯,事实证明,引擎盖下 的CS50库中,指针是 用于整个。 实际上,我们将开始剥离 没过多久回那层。 但事实证明,一个表达式, 一些你可能很熟悉, 特别是那些更舒适, 实际上是一个非常受欢迎的 网站,或者堆栈溢出, 这些天。 但是,这实际上有很 技术含义。 我们现在知道堆栈是什么。 这就像一摞托盘 内的食堂。 或您的计算机内的 内存它的那些帧 所使用的功能。 嗯,事实证明,正因为如此 非常简单的实现 所谓的存储器和帧 叠加,实际上你可以控制 一个计算机系统相当容易。 你能砍成一个系统,如果人们 像我们这样没有写我们的代码 特别好。 如果像我们这样的人用大块 内存或使用阵列 - 更常见 - 但有时会忘记检查 我们的数组的边界,你可能 有自己的时候,迭代 路太远结束过去的一个数组。 在最好的情况下,你的程序 可能只是崩溃。 分割故障,善良 尴尬的。 不是很大,但是它不一定 一个非常糟糕的事情。 但是,如果你的程序实际上是对真实 用户的计算机上,如果它的运行 在网站上,实际随机人 在互联网上打,让 人们引发不好的事情,对你的代码 一般不是一件好事,因为 这意味着一个机会,采取 计算机的控制权。 这是怎么回事看 有点神秘。 但我想我会吓唬你 这里最后一个例子。 下面是一个例子的代码。 维基百科有一个很好的 文章,走过 这更多的细节。 我有主的底部电话 富,1 argv中传递。 而这仅仅是这样就可以了 运行程序,并通过 任意输入。 然后foo被宣布往上顶 接受一个字符串,或者更 准确地说,一个char *。 然后声明一个字符数组。 缓冲液,更一般地, 大小为12。 所以,可以装进12个字符 该数组名为c。 然后,它使用这个新功能, 这是新的,但并不难 理解,记忆复制。 将内存复制吧,这是 过去的变量N,无论 用户输入到argv 1到c。 多少个字节? 的字符串长度酒吧。 因此,换句话说,如果用户键入的 H-E-L-L-o输入字符串的长度 你好五。 所以五个那些字节是会得到 复制到阵列名为c, 大小为12。 但是,什么类型的用户在更长 这是13个字符或14字 字符或100个或更多字符? 他们要去哪里去了? 嗯,这架,托盘 在用餐大厅堆栈, 他们去那里。 它只是将开始覆盖 其他的东西,这已经 该堆栈上,满溢 栈,可以这么说。 因此,形象,认为这种方式。 这仅仅是一个多彩版 图片中,我们一直在画画。 在底部,让我们说,是主要的。 和顶部,你现在看到的 的帧,颜色编码,对于一个 名为foo的功能。 但是,什么是有趣的,在这里对 foo是,这里是它的框架。 所以,就像我画 没有,但在淡蓝色的。 现在这是 Ç支架0去。 这是其中c支架 11要结束了。 换句话说,它发生在 被表示为一个正方形。 但如果你只是保持扑通字节 - 煤焦 - 他们将结束 位置0一路上扬 0到11,因为它是建立索引。 但如果是13个字符 要结束了吗? 14日在哪里? 50字符在哪里 要结束了吗? 这将继续下去。 因为即使我们已经得出了 图片与堆栈长大, 事实证明,地址,从 小的地址,小 指针,大的地址。 因此,它只是不断向上和向上。 因此,如果用户键入 你好,这是伟大的。 没有错误,没有问题,每个人的安全。 但是,如果我们的用户类型 调用对抗性的代码,代表 统称为,攻击,攻击, 发作,发作时,会发生什么? 好了,如果所有的输入,用户 键入不只是一些友好 或令人反感的一串字符。 它实际上是一个字符序列 如果你编译它, 它实际上是代码。 也许这是代码,删除所有 您的硬盘驱动器上的文件或发送垃圾邮件 或类似的东西。 请注意,这里的关键是, 如果坏家伙得到了足够幸运 覆盖红色的内存块 - 我没有画上我的照片,但 这个维基百科的图片在这里 - 其所谓的返回地址。 当食品的回报,掉期回报时, 电脑知道如何去从 这里这里? 或者在高科技板块上面,如何 它知道去从交换 代码 - 0和1的 构成掉期 - 回到主? 有一个所谓的返回地址 存储在相同的堆栈帧,在 同一食堂盘。 因此,如果坏家伙是足够聪明, 把攻击代码,攻击代码,攻击 代码,并获得足够幸运 - 往往是通过试验和错误 - 覆盖,红色返回地址, 的地址和通知 极顶。 注意0835C080。 倒着写往上顶 原因也许我们会重新审视。 这是这个数字。 因此,如果坏家伙得到足够幸运或 足够聪明,红色覆盖 剥离用的地址的存储器 他或她有某种代码 注入到你的电脑,你猜的 代码将被返回到 富尽快执行完? 坏家伙的代码。 因此,这种攻击代码,AAA,再次,可能 发送垃圾邮件,可能会删除所有文件 您的硬盘驱动器上。 但是,这是一个真正的堆栈溢出 或缓冲区溢出,或 缓冲区溢出攻击。 这是令人难以置信的,令人难以置信的普遍 这一天,编写的程序 C,C + +,甚至还有一些其他的语言。 在那个可怕的音符,我们将 结束一个笑话。 [笑] 星期三见。 于下CS50 - 所以,我所有的磁盘灯,但今天 等待,无脂牛奶,有一半的手机 书,橙汁 今天我喝。 USB连接线,一个扳手。 [音乐播放]