>> [音乐播放]
>> 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连接线，一个扳手。
>> [音乐播放]