DAVID马兰:你好, 欢迎回到CS50。 因此,这是本周四结束。 刚一公布第一。 因此,所谓的第五个星期一是 上来今年下星期一。 这是改变的机会 SAT / UNSAT一个字母等级,还是从 字母等级SAT / UNSAT。 烦人,这个过程确实需要一个 签名,因为你必须填写 出那些粉红色的分/插形式之一。 因为从技术上说,SAT / UNSAT 版本和信级版本 有不同的目录编号。 但没什么大不了的。 只是过来跟我抢 或在任何点的劳伦。 或给我们发电子邮件,如果你没有那种 你需要的文书工作的今天,我们 一定会帮助您 周一前的护理。 所有权利,所以今天 - 其实,有一点回音。 我们能否音我倒有几分? 确定。 因此,我们今天介绍一个主题 被称为指针。 我承认,这是一个 更复杂的主题,我们倾向于 在这个类中覆盖,或任何真正的 入门课程使用C. 但我的话,特别是 如果你的头脑感觉有点弯曲 今天,在今后几个星期。 这不是你得到的代表 任何在这个糟糕的,那只是意味着 这是一个特别复杂的话题 我答应,几个星期 因此,会显得太惊人 回想起来简单。 我还记得这一天。 我坐在食堂埃利奥特, 坐在旁边我的TF尼沙特梅塔, 谁是居民埃利奥特房子。 出于某种原因,这 只要点击主题。 这是说,我也挣扎 与一定量的时间,但我 会尽我所能来帮助避免任何此类 一个话题,最终的斗争 是相当强大的。 事实上,我们将讨论的话题之一 在未来几周内, 的安全性,以及如何才能真正 利用机器的方式 并不打算。 而那些剥削通常 错误,错误的结果,我们 人们不理解一些使 底层的实现 通过哪些程序。 现在这个问题似乎更多的用户 友好的,我想我会打10 一个小的黏土动画的第二个预览 数字命名宾基被带到 在斯坦福大学生活,我们的一个朋友, 教授尼克Parlante。 所以,请允许我把这个给你 这里传情宾基。 [视频回放] 嘿,宾基。 醒来。 它的时间的指针乐趣。 - 那是什么? 了解指针? 哦,满载而归。 [END视频播放] 国宝马兰:这是斯坦福 计算机科学。 所以来。 [掌声] 国宝MALAN:对不起,尼克。 因此,记得我们最后一次止 这真是令人兴奋的吊人胃口 据此,此功能 只是没有工作。 至少凭直觉,感觉 像它应该工作。 简单地交换值 为两个整数。 但记得,当我们打印出 在主,一个原始值 二,他们仍然是一个和 两个,而不是2个和1个。 因此,让我真正切换 超过家电。 我写了一个骨架代码位 推进在这里,我要求使得x 1,y将是2。 然后,我打印出他们的两个 值打印为f。 然后,我要求在这里, 我们要交换他们。 我们这里给我留下了空白点 填写今天在短短的时刻。 然后,我会要求 已交换两个变量。 然后,我要打印 他们出来了。 所以我希望,我应该看到1,2。 2,1。 这是超级简单 现在目标。 那么,我们如何去交换 两个变量? 恩,如果我在这里提出,这些杯子 可能代表一台计算机的存储器中。 这是了几口,这 是另几叮咬。 我们有一个志愿者和 混合一些饮料,如果熟悉吗? 上来吧。 你叫什么名字? JESS:杰西。 国宝MALAN:杰斯? 上来吧,杰西。 如果你不介意的话,我们必须把 谷歌的玻璃上,所以我们可以 不朽。 OK,玻璃。 录制视频。 OK,我们是很好的 这里去与杰斯。 好的。 认识你很高兴。 所以,我想什么你在这里做 - 如果你能,相当迅速 - 只是我们倒一杯橙汁一半 果汁和一杯牛奶的一半, 较有效的数字1 1杯和2个其他杯中。 这将是很好的素材。 JESS:对不起。 国宝马兰:没有,没有。 这是确定的。 尼斯。 所有的权利,所以我们有四个字节 值得橙汁。 我们将它称为值1。 现在另外四个字节价值的牛奶。 将调用它的价值2。 因此,x和y分别。 所有权利,所以现在如果手头的任务 - 你,杰西,眼前的一切 你的同学 - 是交换的值的x和y这样的 我们希望在橙汁 其他杯和这杯牛奶,如何 你可能会 - 之前,你居然做 - 去这样做呢? OK,明智的决定。 所以,你需要多一点的内存。 因此,让我们分配一个临时的 杯,如果你愿意。 现在进行交换x和y。 优秀的。 所以做得非常​​好。 谢谢你这么多,杰西。 给你。 一个小纪念品。 OK,所以很明显,超简单的想法。 完全直观,我们需要一点点 更多的存储空间 - 在这种形式中, 一杯 - 如果我们真的要 交换这两个变量。 因此,让我们做。 在这里,我要求我之间上升 我会做一些交换, 走并宣布温度。 我会设置它等于说,X。 然后,我要改变的价值 x刚刚像杰斯这里 牛奶和橙汁 等于y。 我要改变将y等于 而不是x,因为现在我们将 停留在一个圆圈,而是温度。 我暂时 - 杰斯 暂时把橙汁 前重挫, 一杯牛奶。 所以,让我继续前进,使这个。 它称为noswap.c。 现在让我们我运行没有交换。 事实上,我看到的,如果我扩大 窗口一点点, x为1时,y是2。 然后,x是2,y是1。 但记得,上周一,我们做的事情 一点点不同,让我 而不是实现一个辅助函数, 如果你愿意,这实际上是无效的。 我把它叫做交换。 我给它两个参数,我叫 他们,我叫他们b。 坦白说,我可以给他们打电话x和y。 有什么能够阻止 我这样做。 不过,我会认为它是那么 有点暧昧。 因为周一召回我们 权利,这些参数是 值的副本传入 因此,它只是弄乱你 记住,我觉得,如果你使用 完全相同的变量。 所以,我会打电话给他们,而不是一个 B,仅仅是为了清楚。 但是,我们可以给他们打电话最 我们想要的东西。 我要去复制和粘贴 有有效代码 下来到这里。 因为我刚看到它​​的工作原理。 所以这是相当不错的形状。 我会改变我,我的x x到 ,我的Y b和我的Y到b。 所以换句话说,相同的逻辑。 确切的同样的事情,杰斯做。 然后我必须做的一件事 这里,当然,现在调用当前 函数或调用这个函数。 因此,我会调用这个函数有两个 输入,X和Y,并点击保存。 所有权利,所以从根本上 同样的事情。 事实上,我可能已经作出计划 不必要的复杂 写一个函数,这只是服用 约6行代码,而我 此前实施 这个只有三岁。 因此,让我先走,现在改造 这一点,没有掉。 好吧,我搞砸了这里。 这应该是一个错误,你可能 看到越来越普遍作为 程序变得更加复杂。 但有一个简单的办法。 让我向后滚动在这里。 什么是我看到的第一个错误? 隐式声明。 通常什么指示? 哦,我忘了原型。 我忘了教的编译器,交换 会存在,即使他 在开始时不存在 的方案。 所以,我只是说无效,交换, INT,一个int B,分号。 所以我不打算重新实现它。 但现在它匹配这里。 和通知,没有一个分号 这里,这是没有必要的时候 实施。 因此,让我重拍,没有掉。 好得多。 运行没有交换。 该死的。 现在我们回到我们上周一, 那里的东西也不会掉。 有什么直观的解释 为什么是这种情况呢? 是吗? 学生:[听不清]。 DAVID马兰:没错。 因此,a和b是x和y的副本。 而事实上,任何时候,你已经 迄今为止,调用一个函数 通过像整数变量 - 只是作为交换期待 - 你们已经通过副本。 现在,这意味着它需要一点点 的时间内,第二次分裂, 计算机从一个复制位 变到另一个位。 但是,这不是什么大不了的。 但是,他们却一个副本。 所以现在,在交换的背景下, 事实上,我在成功 改变a和b。 事实上,让我们做一个快速 完整性检查。 打印F A%,新生产线。 让我们插上了。 现在让我们做同样的事情,用b。 让我们在这里做同样的事情。 现在,让我复制这些相同的行 再次在底部的功能 后,我的三个有趣的线 可以执行, 再次打印a和b。 所以,现在让我们做,没有掉。 让我一个终端窗口 高一点,这样我们就可以看到 它一次。 和运行没有交换。 x为1时,y是2。 a是1,b是2。 然后,a为2,b是1。 因此,它是工作,就像杰西 在这里做过内部的交换。 不过,当然,它不具有效果 主要变量。 于是,我们看到了一招,让我们 可以解决这个问题,对不对? 当你面对这个范围 的问题,你可能只是平底船,使X 和y变量,而不是什么样的呢? 你可以让他们在全球范围。 把他们在最高层的文件 我们这样做,甚至在比赛中15。 我们使用一个全局变量。 但是在游戏15的上下文中, 有一个全球性的,这是合理的 变量,代表董事会,因为 15.C全部是所有 关于实施的那场比赛。 这就是该文件存在。 但是,在这种情况下,在这里,我 调用函数swap。 我想交换两个变量。 它应该开始觉得只是马虎 如果我们所有的解决方案 当我们碰上范围的问题 问题是使其全球。 因为速度非常快,我们的计划是 要成为相当混乱。 我们这样做绝少 作为一个结果15.c. 但事实证明,有一个 完全有更好的办法。 实际上,让我回去,并删除 打印F的,只是为了简化代码。 让我提出, 这确实是坏的。 但是,如果我不是在一些星号 和星星,我反而可以把这个 成一个功能 实际运作。 因此,让我回到这里,并承认说 星号总是很困难, 所以我会说星星。 我就明说那个。 好的。 而现在,我该怎么 做什么呢? 所以首先,我要指定 ,而不是通过一个int 交换功能,而不是我 去,说INT星级。 现在的明星,什么指示? 这是一个指针,该概念 宾基,黏土动画人物, 指一时年前。 所以,如果我们说诠释明星的意思 现在,不打算要 通过在其价值。 它不会被复制英寸 的地址的情况相反,是 将要传递的。 因此,记得您的计算机内 一大堆的内存,否则 被称为RAM。 而且,RAM仅仅是一个 一大堆字节。 所以,如果你的Mac或PC 两个千兆字节,你有2个 十亿字节的内存。 现在,让我们假设只是为了 保持美好的东西,有序的,我们 分配一个IP地址 - 一个数字 - 在您的计算机上的每一个字节的RAM。 那些2的第一个字节 亿元是由多少个零。 下一个是字节数一数 二,所有的方式起来,点点 点,约2亿元。 所以,你可以的字节数 在您的计算机的内存。 因此,让我们假设,这是什么 我们所说的地址。 所以,当我看到INT星级一个,这是怎么回事 要通过期现掉换是 地址。 不是它的价值,但不论其邮政 地址,可以这么说 - 它的位置在RAM中。 同样为b,我要去 说同样的事情。 诠释,星级,B。 顺便说一句,技术上的明星 在其他地方可以去。 但是,我们将标准化星级 旁边的数据类型。 因此,交换签名意味着现在,给我 一个int的地址和呼叫 地址一个。 并给我的另一个地址 INT和调用该地址b。 但现在这里有我的代码改变。 因为如果我声明INT温度 - 这仍然是int类型的 - 但我存储在它, 什么样的价值? 要清楚,我把一个一个 现在写的代码? 我将在一个位置。 但我不关心 现在的位置,对不对? 温度存在只是杰斯第三杯 存在,目的是什么? 要存储一个值。 牛奶或橙汁。 不实际存储的地址 那些东西,感觉 在这个现实有点无厘头 全球上下文反正。 所以真的,我希望把温度 的地址的情况,但 内容。 因此,如果a是一个数(如123),这是 123字节的内存,一个公正的 恰好是占领,该值 在一个恰好是占领。 如果我想去到该地址, 我需要说一个明星。 同样,如果我要改变什么 地址,我改变 这开始。 如果我要存储在什么 什么位置的位置 B,明星B星。 因此,在短,即使这是不太 下沉还没有 - 我不希望 它会如此之快 - 意识到,我做的是前缀 这些星星我的变量, 说不要抢值。 不要改变值。 而是去到这些地址 和得到的价值。 转到该地址和变化 存在的价值。 所以,现在让我回滚动到顶部, 只是为了解决这条线,在这里, 改变相匹配的原型。 但我现在需要做的另一件事情。 直观地说,如果我已经改变了类型 论点交换期待, 我需要做什么 在我的代码改变? 当我打电话掉。 因为现在,我是什么 我仍然通过交换吗? x的值和y的值,或 牛奶和橙汁。 但我不想这样做。 我不是要传递什么? 的位置x和 y的位置。 什么是他们的邮政地址, 可以这么说。 因此,要做到这一点,有一个符号。 与符号那种听起来地址。 因此n&符号,地址 为x,y的地址。 因此,它是故意的,我们使用 &符号调用函数时, 和恒星时,声明和当 执行的功能。 符号,只是觉得作为 地址运算符,明星的 去那里运营商 - ,或更确切地说, 引用操作 所以这是一个整体的很多话只是 说,现在希望,交换是怎么回事 是正确的。 让我继续前进,使 - 其实,让我们重命名文件,以免 这个程序仍然可以称为无交换。 我要求我们叫它swap.c的现在。 所以,交换。 点,斜线,交换。 现在确实,x为1时,y是2。 然后,x是2,y是1。 好吧,让我们来看看,如果我们不能做到这 有点什么不同 怎么回事。 首先,让我放大我们 这里绘制屏幕。 让我提出了一会儿 - 每当我在这里画将被镜像 那里现在 - 让我提出, 这里有一大堆的内存,或 RAM,在我的电脑里面。 这将是咬号码, 比方说,1。 这将是字节数2。 ,我会尽一大堆, 然后一堆点点点 表明有是2亿美元 这些东西。 4,5,等等。 因此,有前5个字节 我的计算机的内存。 没事吧? 很少有人出2亿美元。 但现在我要建议 以下。 我要建议,x是要 存储数字1,和y会 来存储数字2。 让我去现在领先,并代表 这些值如下所示。 让我们做如下。 给我一秒。 一秒钟。 确定。 我想这一点 - 让我们再次做到这一点。 否则我要使用 相同的号码,无意中, 多次。 所以只是让我们有不同的电话号码, 说说,让这个字节 123,124,125,126, 点点点。 让我要求现在我要去 把值1,值2 这里,否则称为x和y。 因此,它只是恰巧 这是X,这是Y。 只是一些随机的机会, 计算机,操作系统, 碰巧把x的位置 123号。 和Y位置124 - 该死的。 我应该已经解决了这个问题。 哦,男人,我真的想这样做吗? 是的,我想解决这个问题和 b今天这个约是恰当的。 很抱歉,在这个新的。 127,131,我不希望是这样的 复杂,但为什么我改变 有数字吗? 因为我想的整数 实际上是四个字节。 因此,让的这超肛门。 这样,如果发生要处理的 123 2将是在地址 127,因为它是距离酒店仅有4轮空。 这就是全部。 我们会忘记所有 在世界的其他地址。 所以x是在123的位置, y是在位置127。 而现在,其实我做什么 想干什么? 当我打电话期现掉换,有什么 实际上是怎么回事呢? 好吧,我调用swap时,我传递 的地址x和y的地址。 因此,例如,如果这两个条 现在的纸张代表两个 参数A和B交换,我是什么 打算写第一, 我要打电话给作为? 没错,123。 因此,我要求的是一个。 这是参数a。 我把x的地址在那里。 那是什么? 那是什么? 没有,没有。 这是确定的。 还是不错的,还是不错的。 所以这是一个。 现在,在第二张纸, 这将是B,我是什么 要编写上 一张纸吗? 127。 因此,唯一的改变,因为 这个故事我们以前有说服力的是, 而不是字面上的1和2,我 要通过123和127。 我现在打算把这些内部 这个盒子,所有的权利? 所以,现在黑盒子代表 交换功能。 同时,让我们现在有一个人 实现交换功能。 会有人在这里 喜欢做义工? 上来吧。 你叫什么名字? 查理。 好吧,查理。 上来吧。 因此,查理是要发挥 我们黑匣子的作用。 查理,我想请你做什么 现在以这样的方式实现交换 的是,由于这两个地址, 你实际上会 改变值。 我会在你耳边低语 如何运行这里的电视。 所以先走了,你的黑盒子。 到达那里。 你看到什么样的价值观, 为B你看什么样的价值观? 查理:一个是123,b是127。 国宝马兰:OK,正好。 现在停在那里只是一瞬间。 第一件事,你现在打算怎么办, 根据代码 - 现在我会拉在屏幕上 - 将是分配一点 位的内存称为温度。 所以,我要继续前进, 给你的记忆。 因此,这将是第三个变量 你有访问 你名为温度。 你有什么打算写 上临时纸上? 查理:指针,对不对? 国宝MALAN:“确定”,远的不 一定指针。 所以我的代码行 上突出显示在右手边, 我们从这里开始。 一个明星说。 所以目前保存 数字123。 只是直觉,什么 星级123是什么意思? 但是,具体地,如果a是 123,一个明星意味着什么? a的值。 或者更随意,去那里。 因此,我建议,持有中 你的手,继续和治疗 就好像它是一个地图。 走自己电脑的 内存,并找到我们的是什么 在123的位置。 没错。 所以我们看到在位置123 是什么,很明显吗? OK,所以什么样的价值现在是你 去付诸温度? 没错。 因此,继续前进,并做到这一点。 写数字1片 纸的温度题为。 而现在的下一个步骤即 你要实现 会是什么。 以及,在右手侧的 下一行代码是星级住宿。 ,, 当然,存储一个地址。 地址127。 星b表示什么,随便说吗? 进入到该位置。 因此,继续前进,并找到我们什么 在127的位置。 确定。 当然,在位置127, 仍然是值2。 那么你现在店 无论是在上面的位置? 所以明星的手段去的位置。 是什么位置? 没错。 所以,现在,如果你想改变 什么是在那个位置 - 我会继续运行 橡皮擦都在这里。 现在把它刷上。 你打算写什么号码 在该空白框现在呢? 没错。 所以这行代码,要明确 - 让 我暂停了查理的做 这里指出,他刚刚做了什么 写入那个盒子位置123 以前在b的值。 所以我们现在确实实施 这第二行代码。 不幸的是,现在有 还有一个剩余行。 现在是什么温度,从字面上看? 这显然​​是头号。 这不是一个地址。 这只是一个号码,排序 从本周一的变量。 而现在,当你说星级B,这意味着 去的地址b,这对 当然在这里。 所以,一旦你到达那里 - 我会继续前进,抹去了实际上 - 你是什么 去现在写地点127? 查理:温度,这是一种。 DAVID马兰:温度,是其中一个。 和温度到底发生了什么? 好了,我们真的不知道。 我们不在乎。 任何时候,我们已经实现了一个功能 到目前为止,你有任何局部变量 确实是本地的。 他们只是消失。 他们回收经营 最终系统。 因此,温度的事实,仍然有 数值1是一种从根本上 无趣我们。 好吧,让掌声雷动 如果我们能为查理。 非常出色。 好,那么还有什么不 这意味着我们可以做的吗? 所以,事实证明,我们已经 告诉一些善意的谎言 相当长的一段时间。 事实上,它变成了一个字符串, 这段时间,是不是真的 本身的字符序列。 样的,直观的。 但是从技术上来说,字符串是一个 数据类型,我们内部声明 CS50库简化了世界 类的头几个星期。 字符串真的是地址是 一个字符在RAM中的某个地方。 一个字符串,是一个真正的号码,如123 或127,出现这种情况划定 字符串开始 您的计算机的内存。 不过,这并不代表 字符串,每se,本身。 我们可以看到如下。 让我去进取,不断开拓 一些代码之间 今天的源代码示例。 而且我要继续前进,并打开 ,让我们说,比较0.C。 这是一个错误的程序会 以如下方式实现。 第一。 我要说什么。 然后,我要继续前进, 从用户得到一个字符串 在该下一行。 然后,我要再说一遍。 然后我会得到另一个 来自用户的字符串。 通知,我展示之一 字符串中的变量称为S, 另一个这些字符串 在一个变量名为t。 现在,我要索赔,非常 合理,如果s等于等于T, 字符串是相同的。 你键入同样的事情。 否则,琴弦 不一样的东西。 毕竟,如果我们输入两个整数,两 字符,两个浮筒,两个双打,任何 我们谈过的数据类型 迄今为止对它们进行比较 - 记得我们前一阵子很清楚 你不这样做,因为一个 当然是一个等号 赋值运算符。 因此,这将是一个错误。 我们用平等等号, 这确实比较 事情真正的平等。 不过,我要求这是越野车。 如果我继续前进,使比较零, 然后做点斜线比较为零。 我输入,让我们说,你好。 然后让我们再次问好。 从字面上看同样的事情,电脑 索赔我打不同的事情。 现在,也许我只是打错了。 这个时候,我会输入我的名字。 我的意思是,你好。 你好。 这是不同的,每一次。 那么,这是为什么? 到底发生了什么 引擎盖下? 那么,什么是真正回事下方 引擎盖然后是字符串 我输入的,例如首次 这个词打招呼,当然。 但是,如果我们代表这底下 引擎盖,回想一下, 字符串是在一个数组中。 我们已经说了这么多了过去。 所以,如果我画这样的数组,我 要代表的东西相当 类似刚才我们所做的事情。 并有实际的东西 特别在这里,太。 我们什么确定 每一个字符串的结尾? 是啊,这反斜杠零,这是 只是表示方式, 从字面上看,00000000。 八0位成一排。 我不知道,坦白说, 什么是在这之后。 那只是一堆更多的RAM 我的电脑里面。 但是,这是一个数组。 我们谈到阵列。 我们通常谈论数组 作为零的位置, 再一个,然后两个。 但是,这只是为了方便。 而这完全是相对的。 当你实际上得到内存 电脑,当然,任何 2十亿一些奇怪的字节,有可能。 所以,真正的引擎盖下方, 这一切的时候,是的。 这很可能是支架为零。 但是,如果你挖更深下方 油烟机,这是真的 解决123号。 这是地址124。 这是地址125。 而且我没有搞砸这个时候。 这些都是现在一个字节 除了由于什么原因? 一个char有多大? 一个char是只是一个字节。 一个int通常是四个字节。 所以这就是为什么我做了它123, 127,131,等等。 现在,我可以保持简单的数学 只是做加1。 这是现在到底发生了什么 引擎盖下。 所以,当你宣布这样的事情, 字符串s,这其实是 - 原来 - 字符的明星。 明星,当然,这意味着 地址,又名指针。 因此,它的东西的地址。 这是什么地址? 那么 - 我是唯一一个谁可以看到非常 重要的一点,我在做,还是觉得 我做。 所以字符串 - 可悲的是,我有一个监视器 那里我 能看到的是。 所有的权利,所以字符串s是什么 我先前声明。 但事实证明,由于一个小 神奇的的CS50库中,这一切都 从字面上有时间字符串 一直字符星级。 明星再次表示 指针或地址。 事实上,它的侧翼 字字符意味着它的 一个字符的地址。 所以,如果字符串被调用,然后我输入 在H-E-L-L-Ø,现在建议已得到 字串返回 这个时候,即使我们已经相当 过于简单化的世界吗? 没有得到什么实际字符串 作为它的返回值返回? 123在这种情况下,例如。 我们以前说过,得到的字符串 只是返回一个字符串,一个序列 字符。 但是,这是一个有点白色的谎言。 的方式得到真正起作用的字符串 引擎盖下是它得到 来自用户的字符串。 它扑通一声的字符 他或她在内存中。 它把一个反斜杠零结尾 这些字符序列。 但后来没有得到什么字符串 从字面上返回? 它的字面返回的地址 的第一个字节在RAM中的 它用于这种力量。 而事实证明,仅仅通过返回 一个单一的地址的 第一个字符串中的字符,那就是 足以查找的全部 的字符串。 换言之,得到的字符串没有 返回123,124和125。 它没有给我一个长 列表中所有的字节 我的字符串使用。 因为,他们都是背靠背。 和两个,是根据第一个地址,我 可以计算出字符串结束。 怎么样? 特殊的空字符, 结束,反斜线零。 因此,换句话说,如果 你传递 - 内部变量 - 一个字符的地址,并承担 ,任何字符串结束时,任何 作为我们人类的字符序列 想到的字符串,如果你假设 在有任何这样的字符串的末尾 一个反斜杠零,你的黄金。 因为你总是可以找到 字符串的结尾。 现在,什么是真正然后去 在这个程序? 为什么是这样的程序, 比较0.C,越野车? 什么是真正被比较? 是吗? 学生:[听不清]。 DAVID马兰:没错。 它的位置比较 的字符串。 因此,如果用户已键入招呼一次, 像我一样,内存可能会结束 这样看。 然后,如果用户类型招呼再次 但再次调用get字符串,c是 不特别聪明,除非你教 它是巧妙地编写代码。 C - 和计算机更普遍 - 如果你输入单词再打招呼, 你知道你要得到什么。 你只是会得到第二个数组 内存,是的,发生 存储H-E-L-L-O和等等。 看起来是一样的,这是怎么回事 我们人类,但这个地址 可能不是123。 所以它可能只是发生 操作系统具有一些可用的 空间实例在位置 - 比方说,任意东西, 像这样的位置200。 这是201的位置。 这是位置202。 我们不知道这 要存在于内存中。 但是,这是什么意思是,什么是 将最终被存储在s? 123。 这是怎么回事存储在T, 在这种武断的例子吗? 200号。 那么这意味着是显而易见的, 123不等于200。 所以如果条件不 计算结果为true。 由于获取字符串使用不同 每次的内存块。 现在,我们可以再次看到这个 在另一个实例中。 让我去进取,不断开拓复制0.C的。 我要求这个例子是要 尝试 - 失败 - 复制两个字符串 如下所示。 我要说点什么 给用户。 然后,我会得到一个 串并调用它s。 而现在,我做这个检查。 我们提到这一段时间回来。 但是,当可能会返回空字符串, 另一个特殊字符,或特殊 符号让说。 如果它的内存。 例如,如果用户是真的 难以和一个穷凶极恶的类型 上面的的字符数 键盘和点击输入。 如果这个数字的字符就不能 适合在RAM中,不管是任何疯狂 原因,以及字符串可能 很好返回null。 或者,如果你的程序本身是做了很多 其他的事情,而且也只是 没有足够的内存来获取字符串 要取得成功,它可能结束 向上返回null。 但是,让我们更精确 这是什么。 s的数据类型,什么是真的吗? 字符明星。 因此,原来现在我们可以剥离 回空层。 原来,null是 - 是的,很明显 一个特殊的符号。 但什么是真的? 真的,空,我们只是一个符号 人类使用的代表零。 因此,作者的C,电脑 更一般地,决定年前 这一点,你知道是什么。 为什么我们不确保没有用户 数据是永远,永远,永远 存储再见零? 事实上,即使是在我任意的例子 之前,我并没有开始编号 在零字节。 我开始在一个。 因为我知道,人在世界上 已决定预定的零 在任何人的RAM作为字节 一些特别的东西。 原因是,任何时候你想 信号出了毛病 地址中,返回 空 - 否则被称为零 - 因为你知道,有没有 合法的数据地址零,显然 这意味着一个错误。 这就是为什么,按照惯例,我们检查 空和返回的东西 就像一个在这些情况下。 因此,如果我们现在向下滚动,这只是 然后一些错误检查,以防万一 [出事了?保释?] 完全退出程序 通过提前回国。 现在这条线可以改写 因为这,这意味着什么呢? 在左侧,再给我一次 指针指向一个字符,并调用它吨。 我是什么存储里面的t,根据 这一行代码? 我存储的位置。 具体来说,位置 这是在s。 因此,如果用户已键入招呼, 你好,第一恰好结束 在这里,然后数123 要回来得到 串并储存 - 正如我们前面所说 - 在s。 当我现在宣布另一个指针 一个char并调用它的T,什么号码 从字面上去结束在 吨的故事? 所以123。 所以现在技术上s和 T是指向的确切 相同的内存块。 所以通知我要现在做什么 证明,此计划是马车。 首先,我稍后会要求, 打印F,资本化 拷贝的字符串。 然后我会做一个小小的 错误检查。 我要确保。 让我们确保该字符串t是 至少大于零的长度, 所以有一些字符 实际利用。 然后你可能还记得这个 从前面的例子。 2上 - 这是在 ctype.h的文件。 Ť支架零给我零 字符的字符串t。 和2上相同的值, 当然,将其转换为大写。 所以凭直觉,这突出显示的行 代码是资本化的第一 在T字母。 但它不直观,转增股本, 在s的第一个字母。 但是,如果你超前的思维,我是什么 看当我运行这个程序 并打印出原来, s,而所谓的副本,T? 他们实际上是相同的。 他们为什么会是一样的吗? 他们都指向 完全一样的东西。 因此,让我们做到这一点。 使副本为零。 编译OK。 让我跑副本为零。 让我键入类似您好 全部小写,然后按Enter键。 它声称原来的S 副本的确是相同的。 所以,这里到底发生了什么? 让我重绘此图片 在讲故事 稍微不同的方式。 到底发生了什么下方 当我声明类似罩 字符开始,或字符串s 我得到一个指针 - 这恰好是四个字节 的CS50器具中 和很多计算机。 我要调用这个S。 而这目前有 一些未知的值。 当你声明一个变量,除非你 自己把一个价值在那里,谁 知道那里有什么。 这可能是一些随机序列的 位从以前的执行。 所以,当我在我行的代码做 字符串,然后存储返回 价值得到字符串s中不知何故 - 我们最终会剥离怎么弄 字符串的作品,以某种方式分配 可能看起来的阵列 这有点像。 H-E-L-L-O,反斜杠零。 让我们假设这是地址 123只是第一次一致性。 因此,获得字符串返回,在 有突出显示的行,它返回 我们说的号码,123。 那么什么真正走进这里的s? 嗯,真的什么 里面的s是123。 但坦率地说,我开始有点 所有这些地址混淆, 所有这些任意数字。 123,124,127。 因此,让我们简化 世界一点点。 当我们谈论指针,坦率地说, 我们人类,他们到底在乎 事情是在内存中? 这完全是任意的。 这将取决于如何 多少内存的用户。 这将依赖于在白天的时候 你运行的程序,也许和 输入用户给你。 我们居住不重要的细节上。 因此,让我们抽象掉,并说, 当你运行一个像这样的代码行, 字符明星就会越来越回报 获取字符串值。 为什么我们不而是画什么,我们 保持通话就好像它是一个指针 指着东西? 因此,我要求现在到了 有一个指针指向 - 引擎盖下,它是一个地址。 但它只是指向 第一个字节 字符串,被退回。 如果我现在回到这里的代码, 在这条线是怎么回事? 那么,在现在这个突出的线路, 我声明显然是另一个 变量名为t。 但它也是一个指针,所以我要去 画,从理论上讲,确切的 同样大小的方块。 我要调用它吨。 现在,如果我们去回到代码, 当我存储里面的T, 技术上我是什么 把里面的t? 那么从​​技术上说,这 是数字123。 所以,我真的应该写 有数字123。 但是,让我们把它更高的水平。 T,如果它仅仅是一个指针, 直观的,就是这样。 这是所有被 存储在那里。 所以,现在在最后一个有趣的线 代码,当我真正去了解 资本化零字符 T,是怎么回事? 那么,T支架零现在指向 什么样的性格,想必? 它指向到h。 因为T支架零 - 记得,这是旧的语法。吨支架 只是意味着,如果t是一个字符串,T零 支架零意味着零 在这种力量的人物。 所以,真正意味着什么 到这个数组 - 是的,这可能是123, 这可能是124。 但它是相对的,记不清了。 每当谈论一个数组,我们有 谈论的优势 相对指标。 所以现在我们可以假设 那件T支架零小时。 所以,如果我叫2上就可以了,那是什么 真正做的是资本 大写小写h H. 不过,当然,什么是S? 它指向相同织补字符串。 因此,这是已经发生 在这段代码中至今。 那么什么寓意? 我们如何解决这两个问题呢? 我们如何比较实际的字符串? 直观地好了,怎么会 你去比较两个 真正的平等的字符串? 是什么意思,如果两个 字符串相等? 显然不是,他们的地址是 等于在内存中,因为这是一个低 一级执行细节。 所有的字符是相同的。 所以我建议,让我介绍一下 在一个compare.c版本 在这里,所以比较1.C。 最后,我提议,我们仍然获得了 指针,和存储在它 获取字符串返回值。 让我们做同样的事情与t。 因此,没有代码是不同的。 我要加少许 更多错误检查现在。 所以,现在我们有点脱皮 这层CS50什么字符串 实际上,我们需要更肛门 关于如何确保我们不要滥用 无效的值,如空。 所以我只是去检查。 如果s不等于空,T不 等于空,这意味着我们确定。 获取字符串没有搞砸得到 无论是这些字符串。 你也许可以猜到现在, STR CMP也许可以做到吗? 字符串比较。 所以,如果你已经在Java程序之前, 这是像equals方法 string类。 但是,对于那些你们谁没有 编程之前, 这仅仅是一个C函数。 它发生在 文件名为​​string.h中。 这就是它的声明。 和字符串比较 - 我居然忘记了它的用法, 但从来没有介意。 回想一下,我们可以做 人,搅匀比较。 这是怎么回事,弹出 Linux程序员手册。 和它的,坦率地说,有点神秘。 但我可以在这里看到,没错。 我必须包括string.h中。 这里说下描述,“ 字符串比较功能比较 两个字符串S1和S2。而S1 和S2是显然是两个 参数传入​​。 我真的不记得什么 const是,但现在发现 - 你可能已经看到了这一点时,已经 你使用的手册页,如果你 拥有这一切 - 字符星级只是代名词 字符串。 因此,比较这两个字符串S1和 S2,并返回一个整数减 于或等于或大于零的 如果发现S1,分别是 小于或匹配,或者 大于S2。 这只是一个非常复杂的方式说 字符串比较回报 零,如果两个字符串,可以直观地 相同的字符 对于字符。 它返回一个负数,如果 ,按字母顺序排列,应该是 来之前吨。 或者返回一个正数,如果 s是应该来后t 按字母顺序排列。 因此,这个简单的函数,可以 例如,排序 一大堆的话吗? 因此,在这个新版本中,我要去 继续前进,做比较。 点斜线比较。 我会全部小写键入打招呼。 我要键入你好的 再在全部小写。 幸好现在实现 我输入了同样的事情。 同时,如果我输入打招呼较低 情况和Hello大写 对它们进行比较,我打 不同的事情。 不仅是因​​为地址 不同的,但我们比较 不同的字符一遍又一遍。 那么让我们去修复一个 现在其他问题。 让我打开一个版本 复制,现在解决 这个问题如下。 而这个人会看 更复杂一点。 但是,如果你想想什么问题,我们 需要解决,希望这将是 现在只是一瞬间清除。 因此,这第一线,烧焦启动T,在 通俗地说可能有人提出 这条线在这里是指什么? 字符明星T,这样做是什么? 好。 创建一个指针,指向某些 现货在内存中。 让我提炼它一点点。 声明一个变量将存储 一些字符在内存中的地址,只是 要适当多一点。 好了,现在在右手侧,我 从来没有见过这些功能之一 之前,malloc的。 但是,什么意思呢? 分配的内存。 内存分配。 因此,原来,到现在为止,我们 还没有真正有强大的方式 要求的操作系统, 给我一些内存。 相反,我们现在有一个函数调用 malloc的正是这么做的。 尽管这是一个有点 现在分心,注意到,在 两个括号之间是 只是要一个数字。 我输入问题 商标可以是一个数字。 而且这个数字意味着, 给我10个字节。 给我20个字节。 给我100个字节。 和malloc将尽最大努力 要求操作系统 - Linux中,在这种情况下 - 哎,他们的100个字节 可用的RAM? 如果是这样,我返回这些字节 返回的地址中的哪一种 这些字节,也许? 第一个。 因此,这里太 - 这是占主导地位 在C中,任何时候你 处理地址? 你几乎总是处理 第一个这样的地址,不管有多大 你被一块内存 传回,可以这么说。 因此,让我们在这里潜水。 我想怎么分配 多少个字节,到底是什么? 嘛。 字符串的长度为S - 让 做一个具体的例子。 如果你好s是,H-E-L-L-O,什么是 字符串的长度,显然? 因此,它是五。 但我在做加1,为什么呢? 为什么我要六个字节 而不是五个? 空字符。 我不想离开这 特殊的空字符。 因为如果我做一个副本您好 只是做H-E-L-L-O,但我不把 特别字符,电脑 可能没有,一次偶然的机会,一个反斜杠 零对我有。 所以,如果我试图找出 副本的长度,我可能会认为 这是20个字符长,或者一百万 如果我只是从来没有发生字符 打反斜线零。 因此,我们需要6个字节来存储 H-E-L-L-O,反斜杠零。 然后,这仅仅是 是超肛门。 假设,我忘了什么 一个char的大小。 我们一直说这是一个字节。 它通常是。 从理论上讲,它可能是一些 不同,在不同的Mac或 不同的PC。 因此,原来有这个操作符 叫的sizeof,如果你传递给它 名称的数据类型 - 像 char或int或浮 - 它会告诉你,动态的,有多少 字节一个字符占用 特定的计算机。 因此,这是有效的只是 好像是说次1或 时间什么都没有。 但我这样做只是为了超级肛门, ,一个char以防万一不同 在您的计算机与矿山,这样一来 数学总是要退房。 最后,这里我检查null 这始终是很好的做法 - 再 任何时候,我们正在处理的指针。 如果malloc是不是能够给 我6轮空 - 这是 可能性不大,但以防万一 - 马上返回一个。 而现在,接着复制 的字符串,如下所示。 这是熟悉的语法, 尽管在不同的角色。 我要继续前进,让字符串 s的长度,并将其存储在n。 然后,我要循环从i等于 零和包括正, 大于或等于。 因此,在每次迭代中,我把 在第i个字符的第i个 字符的t。 所以,到底发生了什么,上下方 这里的引擎盖? 好吧,如果这样,例如,S - 我已经输入字H-E-L-L-O 并有一个反斜杠零。 再次强调,这是这里的指点。 这里现在是t。 这是现在指向 副本内存,对不对? malloc函数有给我一个完整 的内存块。 我不知道最初是什么 在所有这些位置。 所以我打算把它们看作 一大堆问号。 但只要我一开始从零循环 向上穿过的长度,吨 支架零和t支架1 - 我会立即把这个 上的开销 - 零吨支架和s支架零的意思 我要复制 迭代ħ在这里,E-L-L-O。 另外,因为我做的加 ,反斜线零。 所以现在比较1.C的情况下, 在年底,如果我打印出来的 资本的t,我们应该 看到,s是不变的。 让我现在继续做这个。 所以COPY1。 点斜线副本1。 我打招呼,输入要输入。 现在注意到,只有副本 已被资本化。 因为我确实有两个 内存块。 不幸的是,你可以做一些漂亮的 这里坏,相当危险的事情。 让我拉起一个例子现在在这里, 为我们提供了一个例子,几个 不同的线路。 所以只是凭直觉在这里,第一行 码,诠释星级的x,正在申报 一个变量x。 ,什么是数据类型 该变量? 该变量的数据类型是什么? 这不是吊人胃口。 的数据类型为int的明星。 那么,到底是什么意思呢? X的 一个int存储地址。 就这么简单。 Y为要存储 一个int地址。 第三行是什么 代码做什么呢? 它的分配多少 字节,最有可能? 四。 由于一个int的大小是 一般四,四的malloc给 我回了一大块地址 内存的字节的第一个是 现在存储在x。 现在,我们正在一点点迅速。 星x表示什么? 这意味着进入该地址 并提出有什么号码? 将有数字42。 星y表示在y 把有13号。 但是且慢。 y中的那一刻是什么? 什么地址为y存储? 我们不知道,对不对? 我们从来没有一次使用赋值 运营商涉及Ÿ。 所以y在第二行的声明 代码只是一些垃圾值,大 问号可以这么说。 它可以指向随机 在内存中的任何事情,这 普遍不好。 所以只要我们在那里打线, 星级y等于13,坏的东西, 太差的东西大约是 发生宾基。 因此,让我们看看会发生什么结束 发生在这一分钟宾基 左右的样子。 [视频回放] 嘿,宾基。 醒来。 它的时间的指针乐趣。 - 那是什么? 了解指针? 哦,满载而归。 好吧,上手,我想我们 将需要一对夫妇的指针。 - 确定。 该代码分配两个指针 它可以指向整数。 OK,好了,我看到两个指针。 但他们似乎没有要 指向任何东西。 这是正确的。 最初,指针不 指向任何东西。 它们指向的东西被称为 指针对象,设置起来是一个 单独的步骤。 哦,对,没错。 我知道。 指针对象是分开的。 那么你是怎么分配一个pointee的? - 确定。 那么,这个代码分配一个新的整数 指针对象,而这部分集合X 指向它。 嘿,这看起来更好。 所以,让它做点事。 - 确定。 我会取消引用指针x到存储 42号及其指针。 对于这一招,我需要我的魔法 魔杖提领。 你的魔杖提领? 呃,这是伟大的。 这是什么样的代码看起来像。 我刚刚设立的数量,以及 - 嘿,看。 就这样吧。 这样算下来,反引用X服从 箭头访问及其指针。 在这种情况下,在那里存储42。 嘿,尝试用它来存储数字 13通过其他指针,Y。 - 确定。 我就在这里为y,并且 13号成立。 然后拿魔杖 提领,只是 - 哇! 哦,嘿嘿。 这没有奏效。 宾基说,我不认为 提领y是一个不错的主意, 因为设立的pointee, 是一个独立的步骤。 我不认为我们曾经做到了。 嗯。 好点。 是的,我们分配的指针y。 但是,我们从来没有将其设置为 指向的pointee。 嗯。 非常细心。 嘿,你看 好,宾基。 你可以解决它,使y点 到相同的指针对象为x? - 当然。 我会用我的魔杖 指针赋值。 -IS将是一个 像以前一样的问题? 没有。 这不触摸指针对象。 它只是改变了一个指针指向 作为另一个同样的事情。 哦,我明白了。 y点为x到同一个地方。 所以等待。 现在y的固定。 它有一个指针对象。 所以,你可以尝试魔杖 再次提领 送13以上。 - 确定。 这里去。 嘿,看看那。 现在提领工程对y。 而且,由于指针共享 那一个指针对象,他们 看到13。 呀。 共享。 不管。 所以我们现在去开关的地方吗? 哦,看。 我们没时间了。 但是 - 只要记住三个 指针规则。 数一,基本结构 就是你有一个指针。 它指向指针对象。 但是,指针和指针对象 是分开的。 常见的错误是 设立一个指针,但到 忘了给定的指针对象。 两个指针引用开始 上面的指针和如下 箭头的访问及其指针。 正如我们都知道,这只是工作,如果有 指针对象,回来 排除头号。 三,需要指针赋值 一个指针,它指向的变化 作为另一个指针的指针对象。 因此,在转让之后, 两个指针 指向相同的pointee。 有时候,这就是所谓的共享。 而这一切就是这么简单,真的。 再见了。 [END视频播放] 国宝马兰:因此,更多的三分球, 更下周宾基上。 我们会看到你在星期一。