[音乐播放] 戴维·J·马兰:好吧。 这是CS50。 这是5周的开始。 正如你可能已经注意到, 一些材料 越来越多一点 复杂,小更密。 而且它是很容易的,尤其是当 你已经在习惯了一段时间, 是为了要涂下最 什么我们做什么,我们说在课堂上。 但要意识到,这也许不是 理想的教学方法 学习这种物质, 而材料更普遍。 因此,我们很高兴 宣布,CS50自己Gheng 龚已开始准备 一个规范的集合票据 用于操作过程中,希望 其是,一个,这些 不仅作为 参考和资源 审查材料中去 回通过材料可能具有的 逃脱你在第一时间左右,但 也让你的头可以更 向上比下降,当它 谈到时间来讲课, 所以,你可能搞 更周到,为 相对于更杂乱。 虽这么说,你会发现 该网站是这样的文件,因为这。 并请注意,在左上角,有 不仅表的内容, 而且时间码的 会立即跳到你 到相应的部分 在视频网上。 什么常在这里做了 在本质上,记载 发生了什么事在这 特别讲座。 和许多的讲座是 已经在线使用这个网址。 我们将继续张贴其余 那些在本周末结束, 所以不要采取资源优势。 因此,事不宜迟, 我们开始剥离回 已经作为层 串持续一段时间。 并没有说什么一个字符串 上周居然是? 因此,焦炭的明星。 和CHAR星,那么, 这样做究竟意味着什么? 那么,这一切的时候,如果我们已经 被调用的函数, 喜欢的getString和存储 所谓返回 的getString的价值 变量 - 这就是所谓的 S型string--我们已经写 这行代码在那里上面。 而且它是只有当我看到我的 在这里手写放大 我意识到多么恶劣,这是。 但是,让我们假设, 在右手侧 是,但是,合理的 一个什么样的描述 一直在进行这一切 时间的getString。 的getString,当然,得到的字符串。 但是,这究竟意味着什么? 这意味着它得到了一大块 来自操作系统的内存 通过调用一个函数,称为malloc的。 但后来更多。 然后填充 该内存块 以字母的用户具有 当然键入,紧接着,, 一个空字符或反斜杠 零在最后。 同时,在左手侧 这个故事,这一切的时候, 我们已经声明了一个变量,如第 而这个变量就是现在 将开始调用的指针。 这不是这里面一箱 我们把串,Daven,本身 而是我们把在这方 箱体左侧究竟是什么? 是吗? 听众:的地址 它位于内存中。 戴维·J·马兰:没错。 Daven的所在地址 位于存储器。 不,所有Daven的所在, 本身,而是专门的地址 什么? 是吗? 听众:第一个字符。 戴维·J·马兰:第一个字符 在Daven,其中,在这种情况下, 我提出了任意 和不切实际1,OX1, 它的意思是, 1的十六进制数。 但是,它可能会 是一个更大的数字 我们可能会得出 以0X作为前缀, 代表一个十六进制字符。 而且,由于我们并不需要知道在哪里 Daven的字符的其余部分 是因为,有什么简单的设计 决定这是多年前? 是吗? 听众:反斜杠0。 戴维·J·马兰:是的,没错。 反斜线0可以让你,尽管在 线性时间,来遍历字符串 由左到右行走, 用for循环,或同时 环或类似的东西 这一点,决定了哦,这里 是这个特定字符串的结尾。 所以只用在地址 字符串的开始, 我们可以访问的全部 它,因为这一切的同时, 一个字符串,刚刚一个char明星。 因此,这的确精致继续使用 在CS50库,而且这样的抽象, 可以这么说,但我们会 首先,看看到底 什么是怎么回事 下面这整个时间。 所以,你可能还记得这个例子中, 同样,从去年的时候,比较0, 这实际上并没有进行比较。 但是,我们开始解决这个问题。 但是作为也许是复习, 我可能感兴趣的人 粉红色的大象的今天, 还长呢? 怎么样,你在前面? [听不清]。 上来吧。 并且在此期间, 你上来,让我们 考虑了一会儿就好了什么 这段代码实际上做的事情。 它声明两个变量了 顶,S和T,并调用的getString。 这不是一个非常用户友好的程序, 因为它不会告诉你的事。 但是,让我们姑且我们 重点是多汁的一部分。 然后我们做的,如果s等于 等于T,应该说printf的, 您键入同样的事情。 你好。 你叫什么名字? 詹妮尔:詹妮尔。 戴维·J·马兰:詹妮尔, 很高兴认识你。 所以,你在挑战 手这头大象 是第一个吸引我们的是什么图片 被代表的前两个 线。 因此,S和T可能是 显示在画面上如何? 而且你可以绘制与 将手指放在这个大屏幕上。 因此,有两部分,以 该方程的每一侧。 所以有S上的左侧,并且 然后GetString的右边。 再有就是吨左边, 然后GetString的右边。 那么我们如何开始 绘制的画面, 表示这是怎么回事 这里的记忆,你会说什么? 让我让你解释 你在做什么,当您去。 詹妮尔:好的。 嗯,首先,它会问 你得到输入字符串。 它会store--哦,对不起。 戴维·J·马兰:确定。 好。 而这个叫什么? 哦,好吧。 继续前进。 我不是故意要打断。 詹妮尔:对不起。 因此,将其输入到 地址of--不能确定。 我不记得确切的数字, 但我相信这是从0开始。 戴维·J·马兰:没关系, 因为我做的数字了, 所以没有正确的答案。 詹妮尔:用0起弧。 戴维·J·马兰:好了,元素0。 当然。 詹妮尔:然后如果是 像刚才两个letter-- 戴维·J·马兰:好了,还给你。 詹妮尔:所以元素0, 然后元件1或元件2。 戴维·J·马兰:而且这一块 图片是你画的权利吗? 给GetString的调用? 或s的声明? 詹妮尔:报关 的S,我相信。 哦,对的getString,因为它会 被输入到每一个[?区。 ?] 戴维·J·马兰:好。 没错。 尽管这有效地 返回一个数组,调用, 当我们回到一个字符串,我们可以 索引使用01和2的字符串。 从技术上讲,这很可能是 个别地址表示, 但是这很好。 于是想,如果我可以快 转发给我们留下了 最后时刻,如果一个 字符串是克A B E, 反斜杠0,从而表示Gabe的 输入,怎么可能,我们代表就谈到? 如果是这样的存储器那 被送回了的getString? 詹妮尔:这将是 由电弧所表示? 戴维·J·马兰:通过电弧? 哦,不。 远的不说,形象地, 让我继续前进 和建议,如果这是秒,这 是的getString的返回值。 而你画这是0,1,2,其中 是完全合理的,因为我们 可以索引到字符串,作为这样。 但刚需一致 最后一次,让我先走 并随意提出这 是地址1,这是地址2, 这是地址3,依此类推。 因此,刚需超 显然,这是怎么回事 s中去,作为一个结果, 代码的第一行,你会说什么? 詹妮尔:地址1? 戴维·J·马兰:没错。 因此,解决为0x1。 而与此同时,让我继续前进, 重复的很多东西,你做 在这里添加自己吨。 如果我要在加布型 再一次,第二次, 当用的getString提示,其中, 当然,被加布要去? 那么,presumably-- 詹妮尔:像在这里? 戴维·J·马兰:是的。 詹妮尔:或者它也是在同一个箱子? 戴维·J·马兰:我建议,是啊, 准确,因此,在这些附加的盒子。 但是,什么是现在的关键是,即使 虽然我画这些八九不离十 together--为0x1,这 被0x2--在现实中, 这个现在可能是地址为0x10, 例如,和为0x11,以及0x12的 等等。 因此,如果是这样的话, 这是怎么回事结束了在这里吨? 詹妮尔:为0x10? 戴维·J·马兰:没错。 因此,为0x10。 所以现在,最后一个问题。 你有,到目前为止,已经工作了 最难的大象迄今。 事到如今,如果我拉起码 再次,当我这样做,在三线, 如果s等于等于T,我算什么实际 相比较,我们在这里画? 詹妮尔:这两个地址? 戴维·J·马兰:没错。 所以,我要说的是S等于等于t? 换句话说,是1等于等于10? 并且,当然,在 答案很明显,现在是,没有。 所以这个方案最终是 要打印的内容,你会说什么? 詹妮尔:它会是这样, 您键入同样的事情? 戴维·J·马兰:所以,如果 s是1和t是10? 詹妮尔:输入不同的事情。 戴维·J·马兰:没错。 你输入不同的事情。 好吧。 所以,掌声雷动, 如果我们能在这里。 [掌声] 这是痛苦的。 我知道。 很好地完成。 所以,现在让我们来看看,如果我们不能 梳理出什么样的修复程序。 当然,当我们固定this-- 现在我将代表green-- 我们做了几个增强功能在这里。 首先,正如一个理智 检查一下,我先检查 如果s等于null和T等于null。 而只是要清楚,如果可能 s或t为null,在这样的代码? 当可能s或t为null。 是吗? 听众:[听不清]。 戴维·J·马兰:没错。 如果字符串用户 键入的是太长时间 要装入内存,或者一些 奇怪的角落情况下那样, GetString的,正如我们所看到的,从字面上 今天,它的文档中, 表示将返回null作为 一个特殊的标记值, 或者只是有点特殊符号 这意味着出事了。 因此,我们要检查 是,因为事实证明 那空是一个非常危险的价值。 通常情况下,如果你尝试做一些与 空涉及函数 - 它传递 作为输入,对instance--该功能 很可能会崩溃,并用它, 记下你的整个程序。 因此,这第三条线,现在仅仅是一个理智 检查,检查错误,如果你愿意。 这是一个好习惯,现在的 我们进入任何时候我们 尝试使用一个值, 可能,可能,是空的。 现在,在第四行此处, “如果STRCMP(S,T),”好了, 那是什么指? 好吧,我们说这是一个非常简洁 命名函数的字符串比较。 及其在生命的目的是比较 其反对的第一个参数第二, 但不是在它们的地址而言, 因为我们没有无意中片刻 以前的红色代码,但 而比较这两个 在力所能及直观的字符串 通过比较这一点,对这种方式, 针对这一点,针对这一点,并 然后停止,如果和当一个 还是我的两个手指 打一个反斜杠0。 因此,有人年前实施的strcmp 实现我们的功能 我们希望我们会得到 仅通过比较两个简单的值。 现在,坦率地说,我把图纸 所有这些不同的数字。 但现实是,我已经 制备这些向上的全部时间。 因此,让我干脆去 而这些乱涂出来 做一个点,在结束 这一天,并向前走, 我们不是真的要关心 有什么解决的事情,其实 在存储器中。 所以,我不会画这些 种数的那么多了, 我只是一个抽象的这个客场 小只箭更友好。 换言之,如果s是一个指针, 好了,让我们只绘制它,从字面上看, 作为一个指针箭头指向 从自身到别的东西, 而不用太担心更多 这些地址的细节 其中,再次,我反正做了。 但是,我们可以看到这些地址, 有时,调试代码的时候。 现在,同时,该计划 当然,在这里的修复, 通过比较该问题 这两个字符串。 但是,我们遇到了另一个问题。 这是从复制 节目最后一次, 因此,我试图利用 在一个字符串仅仅是第一个字符。 但究竟是什么症状 我们看到最后的时候 用户键入一个值,如 加布于小写的S, 那么我们分配s转换T, 如第三行那里, 然后我试图 资本吨支架0? 什么效果 改变吨支架0吗? 听众:它改变了第 戴维·J·马兰:是啊, 我换了S,以及。 因为什么怎么回事? 好吧,让我看看,如果我能清洁 这幅画,如下所示。 如果S是再次,字克, A,B,E,反斜杠,0和s 我们将继续绘制一个框 在这里,但没有更多的地址。 让我们停止做的事情了。 让我们只画一幅画 简化了世界。 当我宣布吨,串T, 创建的内存块。 方碰巧是32 位在大多数计算机上。 事实上,如果你曾经听说过的 具有32位体系结构的计算机, 真正看中的,说话,只是 意味着它采用32位地址。 而作为一个技术不谈, 如果你曾经想知道 为什么旧的电脑,如果你真的 想喝汤起来,有很多的RAM, 只能有一个最大 四个千兆字节的RAM, 好,这是因为,从字面上看, 您的旧电脑只能 计高达4 十亿,4个十亿字节, 因为它是使用32位 号码的地址。 但在任何情况下,在该 比如,故事中的要简单得多。 t是只是一个指针,或 真是一个char星,又名字符串。 怎么办我想更新这幅画 现在的代码,第二行, 点后,点,点? 当我做串T等于Š分号, 请问这张照片改变? 是吗? 听众:[听不清]。 戴维·J·马兰:是的。 没错。 我只是把一个箭头从 吨方块以相同的地址, 在相同的第一个字母给了。 或在技术上,如果这 男人仍然在为0x1, 这是因为虽然我有 这里为0x1和0x1这里。 但同样,谁在乎 关于地址? 只是,现在最重要的想法。 因此,这是这里发生了什么。 所以,当然,如果你做T支架 0,这是数组符号, 的course--坦率地说,它看起来 像有一个数组在这里, 但现在有这样奇怪的事情。 要知道,编程语言, C,为您提供此功能, 由此,即使t是 指针,或s是一个指针, 您还可以使用熟悉的, 舒适的括号 符号去的第一要素, 或所述第二元件,或任何元件 在该指针指向 到,因为,据推测,它 是,因为在这种情况下, 指着一些数组。 那么,我们如何解决这个问题? 坦率地说,这是它得到了 有点麻烦第一眼。 但这里是一个新的和改进的版本。 因此,首先,我越来越 摆脱CS50库, 只是揭露S是真的 一个char明星,只是一个代名词。 和T也是一个char明星。 但对到底是怎么回事 该行的右手侧 其中T是赋值? 什么是malloc的? 什么是strlen的? 什么是的sizeof(char)的? 为什么非得这样做 线看起来那么复杂吗? 它是什么做在一个较高的水平? 什么是存储在T? 是吗? 听众:它的分配 一定量的存储空间。 它的存储,我想, 信[听不清]。 戴维·J·马兰:完美。 完美的。 它分配一个特定的 存储空间量 存储,据推测,未来的信件。 并且特别地,malloc的 因此,返回什么? 听众:返回的[听不清]? 戴维·J·马兰:没错。 返回的内存地址, 这只不过是一个奇特的方式, 返回的地址 该内存的第一个字节。 的责任是我记住 实际上有多少内存I 分配或要求的malloc的。 现在是多少呢? 好吧,即使有 很多括号在这里, malloc的只需要一个参数。 和我指定的字符strlen,所以给 我尽可能多的字节,因为在S, 但新增一个。 为什么呢? 是吗? 听众:反斜杠0。 戴维·J·马兰:没错。 我们必须做一点家务。 所以,因为有一个反斜杠 0,我们最好记住这一点。 否则,我们将 创建一个字符串, 没有特别的终结者。 同时,刚需超 肛门,我的sizeof(char)的, 万一有人跑我 不上CS50设备代码, 但也许在不同的计算机 干脆在那里字符 是一个字节,按照惯例,但有两个 字节或更大的东西不止这些。 这是刚需超, 超级反感的错误。 尽管,在现实中,这是 最有可能将是一个1。 现在,同时,我继续和复制 字符串,T支架i等于吨支架第 我将按照上周的 源代码,看看是怎么回事。 但关键的外卖,以及 我之所以把代码现在绿, 是因为很最后一行 吨支架0等于TOUPPER, 具有的效果 转增股本的字符串? T和/或S? 最后一行代码。 只是T,是因为什么 最少此时, 如果我稍微撤消最后一步, 什么情况是,当我调用malloc, í基本上得到一个内存块 这是相同的尺寸,原来, 因为这是算术我做到了。 我存储在T地址 的内存块。 尽管这看起来不错 漂亮,漂亮,一片空白, 实际情况是有,我们会 保持通话,在这里的垃圾值。 该内存块可能很 也有之前被使用, 几秒钟,几分钟前。 因此,有可能完全是数字 或字母那里,只是偶然。 但他们不是有效的,直到我 我自己填充此块内存 与实际的字符,如我 做在for循环出现。 好吧? 所以,现在的高潮 这三个例子 那名看似打破最后一次, 这个互换的例子,这个功能 在这个意义上制作 它交换a和b。 但它并没有什么其他意义的工作? 是吗? 听众:[听不清]。 戴维·J·马兰:没错。 如果我要调用这个函数 从another--例如 从主一样,在功能 我有一个变量,x和y,当我 上星期,同样的代码, 而我通过在X和Y 以交换,然后调用Swap--这一点, 当然是正确的版本 就是我们即将 see--没有奏效。 那么,什么是定位? 好了,所以才要 显然,让我先走 还有 - 给我1秒在这里,看 如果我能告诉你的最后一个,这 将in--让我们来看看,如果我能找到 这种真正的fast--确定,[听不清]。 好了,它就在那里。 所以忽略我只是键入命令。 我希望它在检索 最后一分钟的一例 从去年的时间,这 现在所谓的无交换。 因此,没有交换的地方 我们离开的最后一次, 因此,我初始化 X要1和y 2。 后来我打电话交换,传递1和2。 然后这个函数 在某种意义上工作, 但它没有永久的 在x和y的影响。 因此,目前的问题是,怎么现在 我们其实解决这个问题? 如何解决在眼前? 那么,在swap.c,今天是新的, 看到一对夫妇的差异。 x和y是相同的。 但显然 约25行有什么不同? 最新消息那里,如果你还记得 它看起来像一秒钟前? 听众:[听不清]。 戴维·J·马兰:是的。 所以连字号是一个新的作品 语法不仅这个程序中, 而且更普遍的CS50。 到目前为止,我不认为 我们见过的任何实例 还是真的在任何谈论他们 细节,不是,也许,抢先其他 在节中,像这样的符号。 嗯,原来符号是 最后张新语法 我们要学习的。 它的意思是在 一些变量的地址。 请问您的地址并点¯x住在哪里? 但ÿ住什么地址? 因为如果 之前根本问题 在x和y分别被传递 作为副本,我们真正想做的事 是提供交换与像宝贝一样 地图,导致其中x和y实际上 在RAM中,从而使 交换可以按照该图 和去哪里x或y标志的地方 和改变实际值1和2 那里。 所以交换需要稍微改变了。 乍看之下,这可能 似乎有点类似于字符的明星。 的确是。 所以a是一个指向什么类型的数据, 在此基础上突出部分? 所以这是一个int。 所以不再是一个int, 这是一个int的地址。 同样,B现在准备 是一个int的地址。 所以,当我现在请交换从主, 我不会给交换1和2。 我要去给它像 牛的东西,黄牛的东西, 两个地址,这将导致 交换自己的实际位置 在我的电脑的内存中。 所以,现在,我剩下的落实 需要改变一点点。 有什么明显的不同,现在 在这三行代码? 有这些该死的明星都 过的地方,好吗? 所以,这是怎么回事吗? 是吗? 听众:这是很明显[听不清]。 戴维·J·马兰:没错。 所以在此context--,这是不 最好的设计决定,无可否认, 几年前。 在这种情况下,其中 你只需要一个明星, 而你没有的数据类型, 如int,立即到左边, 而不是你有一个等号,显然, 在这种情况下,当你说星A, 这意味着去 地址是在一个。 按照藏宝图,可以这么说。 并且同时,在第37行, 这意味着同样的事情。 去的地址,并把什么呢? 不管是在 地理位置使得b指定。 换句话说,去到b。 获得该值。 去和每平等 签署,赋值运算符, 把该值存在。 同样,INT温度仅仅是一个int。 没有什么需要改一下温度。 这只是一个备用的玻璃从安嫩伯格 对于一些牛奶或橙汁。 但我需要说的,去到B。 去那个目的地, 放在那里的温度值。 因此,发生了什么呢? 当我真正称之为交换这个时候,如果 这第一盘在这里代表主, 当第二盘代表交换, 我通过符号x和符号ÿ 从主来交换,只是要清楚, 这是什么堆栈帧接收? 是吗? 听众:[听不清]。 戴维·J·马兰:没错。 x的地址和y的地址。 而你能想到的这些 如邮寄地址。 33牛津街和35 牛津街和你 要移动的两栋楼 这是在这些地方。 这有点荒谬的想法, 但是这就是我们所说的地址。 凡在世界上可以 你会发现这两个整数? 凡在世界上你 找到这两个建筑物? 因此,如果最后,毕竟这个时候我 进入今天的源代码和编译 交换和运行./swap,最后,为 第一次,我们确实看到, 我的价值观的确有 已成功交换。 而现在,我们甚至可以把 请注意这一点,比如,广发银行。 所以,让我去到同一个文件中。 让我继续运行./swap的GDB。 而现在,在交换,我会去 未来,并设置一个断点在主。 现在我要去 继续运行该程序。 现在我们看到我的代码 停在该行。 如果我继续和打印 X,我应该在这里看到的? 这是一个问题。 再说一遍? 听众:[听不清]。 戴维·J·马兰:所以 随机数,也许。 也许我很幸运,它的 优雅而简单,如0。 但也许这是一些随机数。 在这种情况下,我真的很幸运。 这恰好是0。 但它确实是运气, 因为直到我 输入下一个,然后打印x的那 代码行,19行,被执行死刑。 同时,如果我输入下一一遍, 现在打印出Y,我要见2。 现在,如果我输入下一个,它要 变得有点混乱,因为现在, 中的printf会出现在 在屏幕上,因为它没有。 x是1。 让我们再次做到这一点。 而现在,这里的地方 事情变得有趣。 在我打电话交换,甚至一步 进去,让我们一点点偷看。 x是,再次,1。 Y是当然,快清醒 检查,2,所以并不难有。 但是,什么是符号X你是否 答案,它是一种时髦好看。 但INT明星在括号只是 对这种说法GDP的方式是一个地址。 它不是一个整数,它是一个指向 int或以其他方式被称为一个地址。 这是什么疯狂的事? 我们从来没有见过的东西 很喜欢之前。 因此,这是在我的电脑的地址 内存,其中x恰好住。 这是黄牛的东西。 这是坦率地说,为什么 我开始画箭头, 不是数字的, 因为谁真正关心 您的int是在一个特定的 地址是那么大。 但bffff0c4,这些都是 的确十六进制数字, 这是0到f。 因此,我们不会过多纠缠 长在什么地方的东西。 但是,如果我打印出Y, 当然,我看到2。 但符号Y,我看这个地址。 并请注意,为好奇, 相距多远是x和y? 您可以忽略大部分的地址。 四个字节。 而这与我们的一致 早前声称有多大是一个int? 四个字节。 所以看起来一切都排队 很好,你可能希望,在内存中。 所以,现在,让我们快进 这个故事的结尾。 让我们继续前进,步型, 潜入交换功能。 现在发现,如果我输入一个,它的 相同,x的地址。 如果我B型是相同的 到y的地址。 所以,我应该怎样,如果我看到 说,进入地址的? 因此,打印星号标示。 所以,明星意味着去那里,在这种情况下。 &符号意味着什么的地址。 所以,明星的手段1。 并打印星级的住宿给我2。 让我假设,就目前而言, 至少所述代码 现在进入执行即可 通过这种方式的理由。 但我们会在不久重新讨论这个想法。 所以这个版本的互换 现在是正确的,并且允许 我们来交换该特定数据类型。 所以任何疑问然后交换? 在星? 对地址? 你会看到,有 问题集4,排序, 但问题集5,绝对,如何将这些 东西是有用的,并得到更多的 熟悉他们,作为一个结果。 什么呢? 好吧。 所以malloc的是,再次,此功能 刚刚分配内存,内存 分配。 以及为什么是这样有用吗? 那么,这一切的时候, 你一直在使用malloc。 如果你现在怎么考虑的 GetString的作品,据推测,这是 被问的人一大块 记忆,随时在用户键入字符串 在,因为我们肯定 不知道,因为CS50的工作人员, 有多大的字符串,人类 要键入可能。 因此,让我们,第一次,开始 剥开如何CS50库工程, 通过几个实例来 这将导致我们的。 所以,如果我打开gedit的 开拓scanf函数0, 我们将看到下面的代码。 scanf函数0,可以在网站上 今天,有代码相对较少的行 在这里,14至20。 让我们来看看它在做什么。 它声明为int,名为x。 它说像,数请。 而现在它说,scanf函数%I,&X。 因此,有一堆新的东西出现。 但是scanf函数,你可以种思考 作为printf的相反。 printf的,当然,打印到屏幕上。 scanf的排序从用户的扫描 键盘的东西,他或她已经打出来。 %i是一样的printf。 这意味着预期 用户键入一个int。 而现在,你为什么认为我 可能是通过scanf函数&X? 如果目的在scanf生活 是得到的东西从用户 是什么意思 通过它,与X,现在呢? 是吗? 听众:[听不清]。 戴维·J·马兰:没错。 无论我,人,请在我的输入 将被保存在该位置。 这是不够的,还记得,刚 通过在X,因为我们已经看到, 任何时候,你只需通过一个原始变量, 就像一个int,一些其他的功能, 当然,它可以改变 可变的,但不会永久。 它不能对主要的效果。 它只能改变自己的本地副本。 但相反,如果你不这样做 给我实际的诠释, 但你给我方向 在INT,我现在,是scanf函数, 当然,我可以按照这 解决并把一些有 所以你可以访问它。 所以,当我运行这个程序,让我们来看看。 使scanf函数0点斜线,scanf函数0。 如果我现在键入数字 像50,感谢50。 如果我现在键入数字一样 负1,为负1。 我现在键入数字如1.5,HM。 为什么我的程序不理我了? 嗯,因为简单地说,我告诉 只期待一个int。 好吧。 所以这是其中的一个版本。 让我们拿东西了一个缺口, 提出,这是不好的。 而就在这里一个很简单的例子, 怎么我们就可以开始编写代码 其他人可以利用或 做不好的事情妥协。 所以第16行,如此相似 在精神之前, 但我不会宣布它诠释这个时候。 我宣布它炭星,又名字符串。 但是,这究竟意味着什么? 所以,如果我不指定address--和 我打电话是随意,缓冲, 但我可以把它称为为s,是simple-- 然后我做到这一点,给我解释一下, 如果可以的话,基于先前 逻辑是什么scanf函数在做线18, 如果传%s和缓冲区, 这是一个地址? 什么是scanf函数,如果你申请的 完全相同的逻辑版本0, 当将试图在这里做, 在用户类型的东西吗? 是吗? 听众:[听不清]。 戴维·J·马兰:没错。 scanf函数,通过逻辑较早, 将要采取的串 该人的类型化 in--它现在是一个字符串, 它不是一个数,据推测, 如果他或她cooperates-- 并且它会试图把那 字符串在内存中的任何地址 缓冲区指定。 这是伟大的,因为缓冲 的确意味着是一个地址。 但我要求这个节目是越野车的 很严肃的方式,因为价值是什么 默认情况下缓冲区? 我有什么初始化为? 什么的内存块? 我没有,对不对? 所以,即使我已经分配了 焦恒星的不再叫S, 它不是所谓的,buffer--所以 让我们来绘制变量名 现在的buffer--如果我没有 所谓的getString或malloc的位置, 这实际上意味着, 缓冲区只是一些垃圾值。 现在是什么意思? 这意味着,我已经告诉scanf函数 期望从用户的字符串。 而且你知道吗? 不管这件事情是指向 to--和我画问号, 但在现实中,这将是 像OX1,2,3,对不对? 这是一些虚假的价值,仅仅 恰好从之前在那里。 所以,换句话说,它是 仿佛缓冲只是 指着东西在内存中。 我不知道是什么。 所以,如果我输入加布现在,这是怎么回事 尝试把G-A-B-E / 0出现。 但谁知道这是什么吗? 和过去一样,任何 我们试图去触摸时间 不属于存储器 对我们来说,发生了什么事? 或几乎所有的时间。 分段错误,对吧? 这个箭头,我不知道它是 指点。它只是一些随机值。 当然,如果你解释 一个随机值作为地址, 你会去 一些随机的目的地。 所以加布可能确实崩溃 我在这里这种情况下程序。 所以,我们可以做到这一点几乎是坏? 考虑这个第三和 scanf函数的最后一个例子。 这个版本是在何种意义上比较好? 如果你是舒服了 以前的问题,这是更好的。 为什么呢? 听众:[听不清]。 戴维·J·马兰:好。 线16,以便该情况下 较好,在这个意义上 我们是明确的 分配一些内存。 我们不使用malloc, 我们使用了2周 只是声明数组的方法。 而我们在此之前一个字符串说过 是一个字符只是一个数组, 所以这是完全合法的。 但它的,当然,如 您注意,固定的大小,16。 因此,这个计划是 完全安全的,如果我输入 在一个文字串,两个字符的 串,15字符的字符串。 但是当我开始打字16, 17,第18,千字符串, 这里是该字符串将要结束? 这将结束部分在这里。 但谁知道还有什么 超出了界限 这个阵列呢? 这是因为虽然我 在这里宣布16箱。 因此,而不是画出来的所有16中,我们将 只是假装我画16。 但是,如果我再尝试读取字符串 这是更长的时间,如50个字符, 我要开始把 A,B,C,D,X,Y,Z。 这大概是 其它一些内存段 即,再次,可能会导致 我的程序崩溃, 因为我没有要求 事情不止16个字节。 那么,谁在乎呢? 好了,这里的CS50库。 而且大部分这只是 类似的指令往上顶。 该CS50库,这一切的时候, 已经有这一行52行。 我们已经看到的typedef,或 你会看到的typedef 在PSET 4,刚刚创建了一个 同义词其中焦炭明星可以更 简称为字符串。 因此,这是一个 数轮培训 我们已经偷偷使用了引擎盖下方。 同时,这里的函数,getchar函数。 现在很明显,没有身体吧。 而事实上,如果我继续 滚动,我实际上并不 看不到任何的实现 这些功能。 作为一个全面的检查,这是为什么? 听众:[听不清]。 戴维·J·马兰:是的。 因此,这是头文件。 和头文件包含原型, 再加上一些其他的东西,现在看来, 喜欢的类型定义。 但在CS50.c,我们已经 从来没有给你顾左右而言他, 但一直在CS50所有家电 这个时候,内心深处的文件夹, 注意到有一个整体 在这里一堆功能。 事实上,我们向下滚动。 让我们忽略了他们中的大多数现在。 但是,向下滚动到调用getInt 看看调用getInt是如何工作的。 因此,这里是调用getInt。 如果你真的关心如何获得 INT作品,这里是它的文档。 而当中的事 它说的是它告诉你 什么值的范围就可以返回。 它本质上是负面的2十亿 以正面的2十亿,给予或采取。 而事实证明,这一切 时间,即使我们从来没有 有了你检查它, 如果出现错误, 事实证明,所有的 此时,调用getInt有 已返回一个特殊的 常量,不为空, 而是INT_MAX,这是 只是一个程序员的约定。 这意味着这里是一个特殊的值。 请一定要检查这一点,只是 在出错的时候。 但是,我们从来没有困扰 同的是,到目前为止, 因为再次,这 是为了简化。 但如何调用getInt得到实施? 嗯,一,它不带任何参数。 我们知道这一点。 它返回一个int。 我们知道这一点。 那么它是怎样的引擎盖底下工作? 所以这是很明显的无限 环,其中一个至少外观。 请注意,我们使用的getString。 所以这很有趣。调用getInt 调用我们自己的函数,的getString。 现在为什么会变成这样? 为什么我会被防守 在这里行165? 哪些本着可能发生 164,只是要清楚吗? 这是同样的答案和以前一样。 可能仅仅是内存不足。 不顺心的事了的getString, 我们必须能够处理的。 而我之所以不返回null是 即,在技术上,空是一个指针。 调用getInt必须返回一个int。 所以我随意 决定,从本质上讲, 有2十亿,而奋斗,是怎么回事 是一种特殊的价值,我永远不可能 其实获取用户。 这只是一个价值我要去 浪费,代表一个错误代码。 所以,现在,事情变得有点奇特。 它不是完全一样的功能 和以前一样,但它是非常相似的。 所以请注意,我在这里声明,符合 172,无论是一个int n和一个char℃。 然后我用这个时髦的路线, sscanf的,它原来 不扫描从键盘输入的字符串。 它代表着现有的字符串 用户已经键入英寸 所以,我已经叫的getString,这 意味着我有一个字符串在内存中。 sscanf的是什么,你会 调用解析函数。 它着眼于我有串 键入,字符一个字符, 并做一些有用的东西。 该字符串被存储在一行。 我知道,只有通过去 备份在这里,说,哦,好吧, 我把它叫做不发这个时间,但行。 而现在,这是一个有点不同。 但是这实际上意味着,其原因 我们会有点潮手在今天, 我们正在检查 查看该用户键入 与诠释,也许另一个字符。 如果用户输入了一个int,它的 将要被存储在正,因为我 按地址传递这一点, 今天我们看到的新把戏。 如果用户还输入 像123x,使得x 将要结束了 字母字符c。 现在事实证明,sscanf的 告诉我,智能化, 多少个变量是sscanf的 能够成功地填补。 所以通过这种逻辑,如果该函数 我实施的调用getInt, 但我检查, 潜在地,对于用户 已经输入了一个int 其次是别的东西, 什么才是我想要的sscanf的 返回值真的是? 如果目的是要获得 只是从用户的诠释? 所以,如果sscanf的回报 2,是什么意思呢? 用户键入 是这样,从字面上看, 123x,这只是无稽之谈。 这是一个错误,并 我要检查的。 因此,如果这在用户的类型,由 这个逻辑有哪些呢sscanf的回报, 你会说什么? 所以它会返回2,因为 123是要去这里, 而X是要结束在这里。 但我不想在x得到填补。 我想,sscanf会只成功 灌装头的变量。 所以这就是为什么我 想sscanf会返回1。 如果这是有点在头上 就目前而言,这是完全正常。 意识到虽然,其中一个 调用getInt和GetString值 就是我们正在做的啦! 很多错误检查这样使 是,到今天为止,你几乎可以 在你的键盘输入任何东西, 我们会抓住它。 我们肯定的是, 工作人员,肯定不会 在一个错误的来源你 计划,因为我们的防守 检查所有的愚蠢的 的东西,用户可能会做, 如输入一个字符串,当 你真的想要诠释。 因此,对于now--我们就来 回此之前long-- 但是这一切的时候, 的getString和调用getInt有 在使用这种发动机罩下方 内存地址的基本思路。 所以,现在,让我们把事情 对用户来说更加友好。 您可能还记得,从去年宾基 时间 - 如果我的鼠标会cooperate--所以 我们有这个代码,这 坦率地说,是相当荒谬的。 此代码实现了什么 有用的,但它是例子 该教授Parlante 为了表示用于 什么样的是怎么回事 项目涉及内存。 因此,让我们复述这 故事超简要介绍。 这些前两行,在 英语,做什么,会说什么? 就在合理的人,但 稍微专业术语,取刺。 听众:[听不清]。 戴维·J·马兰:好,你确定 地址为你的x和y变量。 不大,因为x和y是未 变量在传统意义上的。 x和y是地址 或者将存储地址。 因此,让我们试试这个一次。 不是一个糟糕的开局,但。 是吗? 听众:[听不清]。 戴维·J·马兰:好。 我认为这是一个小清洁。 声明两个三分球,两个整数。 而我们称他们为x和y。 或者,如果我们画 此为图片,再 记得很简单,所有 我们正在做的与第一线 正在制定一个盒子这样的, 在它的一些垃圾的价值, 并调用它的X,然后 另一个盒子这样的, 与一些垃圾值 它,叫它年。 我们已经声明了两个 三分球,最终 将存储一个int的地址。 所以这一切都在那里。 所以当宾基这样做,则 粘土只是看着这样的。 和尼克刚种 包裹起来的箭, 仿佛他们不是指向任何地方 特别是,因为他们只是 垃圾值。 他们没有明确的初始化 任何地方尤其如此。 现在的下一行 代码,召回,是这样的。 因此,在合理的人性化, 但有些技术英语, 什么是这行代码在做什么? 是吗? 听众:[听不清]。 戴维·J·马兰:完美。 它分配的大块 内存是一个int的大小。 而这一半的答案。 你回答正确 一半的表情。 什么是发生在 等号左边? 是吗? 听众:和受让人 它给变量x? 戴维·J·马兰:和受让人 它给变量x。 总括来说,右侧会分配 足够的内存来存储一个int。 但具体的malloc 返回地址 这大块的内存,您已中 只是建议被存放在X。 那么,尼克做了最后一次带宾基是 他拖着那指针移出,粘土, 现在指向一个内存块白 等于一个int的大小。 事实上,这意味着 来表示四个字节。 现在,代码的下一行 这样做,星x被42。 所以42是简单的 右手侧,生活的含义。 左侧,星x表示什么? 这也可能gone--没关系。 行。 听众:基本上, 进入[听不清] 戴维·J·马兰:好。 听众:[听不清]。 戴维·J·马兰:没错。 左手边是指去为x。 x是地址。 这就像33牛津街,或OX1。 和星x表示去那家 解决和放什么呢? 42。 所以,事实上,这正是尼克做了。 他开始用, 本质上,精神上 用手指指着 的x,下面的箭头 到右侧的白框 侧,并且把数42那里。 但后来事情得到了 有点危险吧? 宾基的即将失去他的头。 星y等于13,运气不好,意味着什么? 所以,明星y表示去的地址y中。 但是,什么是Y中的地址? 好吧,这是垃圾的价值,对不对? 我画它作为一个问号。 尼克画了它作为一个蜷缩箭头。 而且只要你尝试 做明星Y,说去那里, 但没有一个合法的 地址,它的一些虚假的位置, 该计划的要崩溃。 和宾基的头部会 飞了出去,在这里,因为它没有。 所以,最后,这个方案 只是平了破绽。 这是一个错误的程序。 它需要加以固定。 而唯一的办法,真的,要解决它 将是,举例来说,这条线, 我们甚至没有去,因为 程序崩溃得太快。 但是,如果我们要解决这个问题,有什么 效果确实做Ÿ等于x具有? 那么,它基本上是在点ÿ 任何值x指向。 因此,在尼克的故事, 或宾基的故事,无论是 x和y分别为指向 白色块的存储器, 这样一来,最终,当 做明星Ÿ再次等于13, 你最终将在13 适当的位置。 因此,所有这些线路都完美 合法的,除了这一个, 之前,当它发生 实际分配Ÿ一定的价值。 现在值得庆幸的是,你不 要通过推理全部 这些类型的问题你自己。 让我继续前进,开 在这里一个终端窗口 与开拓,就一下, 超级短节目的 也就是那种毫无意义的。 这是丑陋的。 它没有实现任何用处。 但它确实证明问题 记忆,让我们一起来看看。 主要的,超级简单。 这显然​​是调用一个函数, F,然后返回0。 这是一种很难搞砸。 所以,主要是相当不错的,到目前为止。 所以f是有问题的。 只是没放多少 努力为它命名 在这里,以保持重心的代码。 f有两行。 让我们看看现在怎么回事。 这样一方面 这里 - 并让我 与前此一致 example--一方面, 左手侧是 做什么,用英语? 它is-- 听众:创建一个指针。 戴维·J·马兰:创建一个指针 为int,把它x即可。 因此,它的创造者一个箱子 我一直画在触摸屏上。 现在,对右手 当然一面,malloc的, 被分配的内存块。 而只是要清楚,怎么 多少内存是它明显 分配,如果你只是 种做数学题吗? 因此,它是40个字节。 我知道,只是因为我知道的 整数,在CS50器具,至少 是四个字节。 所以,10次4 40。 所以这是存储一个x,地址 第一次出40的整数 已分配的空间回来了, 背,背,背来。 而这正是重点对malloc的。 它并不需要一点点内存 在这里,有一点在这里,在这里一点点。 它为您提供了一个内存块, 连续地,从操作 系统。 现在来谈谈这个, 点¯x支架10等于0? 独断专行的代码。 它没有实现任何用处。 但有意思的是, 因为变量x支架10--? 是吗? 听众:[听不清]? 戴维·J·马兰:X支架 10不必是空的。 空的细节只有进场 用字符串,在字符串的结尾。 但一个好的想法。 有多大这个数组,甚至 虽然我已经分配40个字节? 这是从0到9,对不对? 这10个整数,总。 40个字节,但是10个整数, 索引0到0。 那么,什么是是X支架10? 它实际上是一些 未知的垃圾值。 这是一个不属于我的记忆。 我不应该碰的 字节数41,42,43,44。 我会稍微有点远。 事实上,如果我运行这个 程序时,它很可能会崩溃。 但有时,我们会得到幸运。 所以,只是为了演示 this--坦率地说, 你永远不知道你之前 做它 - 让我们来运行的。 它实际上并没有崩溃。 但是,如果我改变这一状况,为 例如,要像千, 使这真的 故意的,让我们来看看 如果我们可以得到它的崩溃这个时候。 好吧,它没有崩溃。 如何约10万? 让我们来改造它,现在重新运行它。 行。 唷。 好吧。 因此很明显,同样,这些 内存段,可以这么说, 是相当大的,所以我们可以 一次又一次得到幸运。 但最终,一旦你得到可笑 真正炎等在屏幕上, 你触摸记忆真的, 真的不属于你。 但坦率地说,这些 种虫子会 是难当 找出你自己的。 不过,值得庆幸的是,作为程序员,我们有 工具,使我们能够做到这一点的我们。 因此,这是,也许是一 最丑的节目, 比gdb的输出,甚至丑陋。 但它总有一条线或 2是超级有用。 Valgrind是一个程序,可以帮助 你没有调试一个程序,本身 但是发现内存相关 的问题,特别是。 它会自动运行您的代码 你看,至少两件事情。 一,你做了什么 偶然像触摸记忆 那不属于你? 这将帮助你找到这些情况。 其二,它会帮助 你发现了一种叫做 内存泄露,我们有 全然不顾,天真, 一段时间和幸​​福地。 但事实证明,所有的 此时,每当 你所谓的getString在 我们这么多的节目, 你问工作 系统记忆体, 但你有什么回忆 有史以来给它 回来了,做unalloc,或 免费的,因为它的调用。 没有,因为我们从来没有 要求你这样做。 但所有这一次,程序 你一直在写C语言 已经泄漏内存, 要求经营 系统越来越 存储字符串和诸如此类的东西, 但从来没有递了回去。 而现在,这是一个有点 à简单化的, 但如果你曾经运行在Mac或 你的电脑很长一段时间,开 大量的节目, 也许关闭程序, 而即使你的 电脑没有死机, 它变得这么慢得多, 好像真的 使用大量的内存或 资源,即使, 如果你不连 触摸键盘, 可能be--但不always--能 是因为你正在运行的程序 有自己的内存泄漏。 他们不断地问操作系统的更多, 更多的内存,但忘记了它, 实际上并不使用它,但 因此,服用内存离开 从可能希望它的其他程序。 所以这是一个常见的​​解释。 现在,这里的地方Valgrind的公司 输出是完全 残暴的那些少 更舒适的一致好评。 但有趣 东西是正确的在这里。 它告诉我一个无效的写 大小4发生这个程序中, 特别是,在memory.c的第21行。 如果我去到第21行,嗯,的确有 是大小为4的无效写。 为什么大小4? 那么,这number--它 可能是anything--是一个int。 因此,这四个字节。 所以,我把四个字节 他们不属于。 这就是Valgrind的 实际上是告诉我。 此外,它也将 告诉我,因为我们将看到, 当你运行这个在未来的PSET,如果和 当你的内存泄漏,这确实是 我有,因为我打过电话 malloc的,但我并没有实际 叫,在这种情况下,自由 我们最终会看到 是的malloc相反。 所以,现在,我认为,最后一个例子。 所以这一块是一个有点多 晦涩难懂,但它也许是 最大的原因 小心内存, 究其原因,很多节目 和/或Web服务器,甚至到今天, 被接管坏人的地方 在互联网上谁是莫名其妙 发送伪造的数据包到服务​​器 试图破坏您的账户, 或者把你的数据,或只是 一般拿过来一台机器。 缓冲区溢出,随着 顾名思义,手段 不溢出为int,而是一个缓冲区。 和缓冲仅仅是一个奇特的方式 的说这是一串记忆。 事实上,我叫一个字符串 前缓冲区,而不是S,。 因为如果它是一个缓冲, 像在YouTube的意义, 或者您正在观看的视频的任何时间, 你可能已经看到这个词的缓冲, 点,点,点。 这是令人难以置信的烦人。 而这仅仅意味着 您的视频播放器 试图下载大量 字节,大量的字节 从网上的视频。 但它是缓慢的,所以它的尝试 下载了一堆人 填充缓冲器,一个容器,从而使 你有足够的字节,它可以再 告诉你的视频, 不停顿不断。 但事实证明,你可以 有一个缓冲,以这个大。 但尽量把这么多数据 微博,很糟糕的事情可能发生。 因此,例如,让我们来看看 一个例子的这个最终预告片。 这是另一种方案 即,乍一看, 什么都不做超级有用。 它有一个主要功能 调用该函数f。 而且函数f,在这里,有 一个char数组,称为大小12℃,。 然后它用这个 新的函数调用strncpy()函数。 事实证明,这种简单 代码简单的线条,只是两条线, 我们已经做了我的整个程序, 因此,我的整个电脑, 我的用户帐户,我的硬盘 开车可能受到任何人 谁知道,是不够好,运行 这个节目带有一定的命令行 的说法。 换句话说,如果这个坏家伙 通过键入把argvargv [1]内 在键盘非常特制 字符串,而不是ABC,123,但本质上, 代表可执行的二进制符号 代码,一个程序,他或她写道: 用这种简单的方案,这是 代表的数以千计的节目 这同样是脆弱的,敢说, 他或她可以最终删除所有 在我的硬盘驱动器中的文件,得到了 闪烁提示,以便他或她可以 自己输入命令, 电子邮件中的所有文件到自己。 什么我可以做的,他 或她可以使用此代码做。 我们不太解决这事。 而事实上,这将 涉及小图片 这样,我们将很快到来 理解就更好了。 但是今天,让我们结束 什么是有希望稍微 可以理解的XKCD笑话, 直到我们重新开始下一次。 好吧。 星期三见。 [音乐播放] 演讲嘉宾:现在,深 思想,通过Daven法纳姆。 记忆就像是跳进了一堆 金黄的树叶在周日下午。 风拂过,你折腾 hair--哦,我怀念的日子when-- [笑]