1 00:00:00,000 --> 00:00:02,860 [Powered by Google Translate] [第5周] 2 00:00:02,860 --> 00:00:04,860 [戴维·J·马兰 - 哈佛大学] 3 00:00:04,860 --> 00:00:07,260 [这是CS50。 - CS50.TV] 4 00:00:07,260 --> 00:00:09,740 >> 这是CS50,5周。 5 00:00:09,740 --> 00:00:12,900 今天和这个星期,我们介绍了一点点取证的世界 6 00:00:12,900 --> 00:00:14,850 的上下文中的问题设置4。 7 00:00:14,850 --> 00:00:18,480 今天将是一个简短的演讲,因为在这里有一个特殊的事件后。 8 00:00:18,480 --> 00:00:21,940 因此,我们将采取偷看,逗学生和家长的一致好评今天 9 00:00:21,940 --> 00:00:24,600 一些的东西,是在地平线上。 10 00:00:24,600 --> 00:00:29,050 >> 其中,截至周一,你将有一些更多的同学。 11 00:00:29,050 --> 00:00:32,980 EDX,哈佛大学和麻省理工学院的“开放式课程网页”多新的网上倡议, 12 00:00:32,980 --> 00:00:36,730 哈佛的校园(星期一),这意味着星期一上推出 13 00:00:36,730 --> 00:00:40,930 最近的一次统计,你将有86,000额外的同学 14 00:00:40,930 --> 00:00:43,680 将跟随着CS50的讲座和部分 15 00:00:43,680 --> 00:00:45,890 和演练和习题集。 16 00:00:45,890 --> 00:00:51,870 作为这项工作的一部分,你将成为成员的就职类的CS50,现在CS50x的。 17 00:00:51,870 --> 00:00:56,150 作为这项工作的一部分,现在,知道会有一些的积极作为。 18 00:00:56,150 --> 00:01:00,620 要为此做好准备,对于数量庞大的学生, 19 00:01:00,620 --> 00:01:03,820 可以肯定地说,即使我们有108个转录因子和CA, 20 00:01:03,820 --> 00:01:07,560 它不是最好的学生与教师的比例,一旦我们打80000的学生。 21 00:01:07,560 --> 00:01:09,830 我们不打算分级这么多问题集手动, 22 00:01:09,830 --> 00:01:13,050 所以本周推出的习题集将是CS50检查, 23 00:01:13,050 --> 00:01:15,410 这将是一个命令行实用程序在设备 24 00:01:15,410 --> 00:01:17,880 一次,你会得到你以后更新本周末。 25 00:01:17,880 --> 00:01:21,030 您就可以运行命令,check50,你自身的pset, 26 00:01:21,030 --> 00:01:24,770 ,你会得到即时反馈,以您的程序是否正确或不正确 27 00:01:24,770 --> 00:01:27,980 根据不同的设计规格,我们已经提供。 28 00:01:27,980 --> 00:01:30,310 更多的是在问题集规范。 29 00:01:30,310 --> 00:01:34,220 CS50x同学们将利用这一点。 30 00:01:34,220 --> 00:01:36,170 >> 习题集4是所有约取证, 31 00:01:36,170 --> 00:01:38,630 真的,这pset的灵感来自一些真实的东西 32 00:01:38,630 --> 00:01:41,210 因此,当我在读研究生,我实习一段时间 33 00:01:41,210 --> 00:01:45,270 米德尔塞克斯县地区检察官办公室从事法医工作 34 00:01:45,270 --> 00:01:47,660 他们的领导取证调查。 35 00:01:47,660 --> 00:01:50,280 这为我想我提到了几个星期过去, 36 00:01:50,280 --> 00:01:52,720 是质量国家警察或其他人, 37 00:01:52,720 --> 00:01:56,150 他们将放弃硬盘驱动器,CD和软盘之类的事情,比如, 38 00:01:56,150 --> 00:01:58,770 然后的法医办公室的目标是要确定 39 00:01:58,770 --> 00:02:01,470 是否有或没有某种形式的证据。 40 00:02:01,470 --> 00:02:04,730 这是特别调查组,所以它是白领犯罪。 41 00:02:04,730 --> 00:02:10,949 更令人不安的是什么形式的犯罪​​,涉及某种数字媒体的。 42 00:02:10,949 --> 00:02:16,450 事实证明,没有那么多的人写一封电子邮件,说,“我做到了。” 43 00:02:16,450 --> 00:02:20,490 所以很多时候,这些法医学搜索并没有打开所有的东西,水果, 44 00:02:20,490 --> 00:02:22,820 但有时人们会写这样的邮件。 45 00:02:22,820 --> 00:02:25,240 所以有时候,努力得到了回报。 46 00:02:25,240 --> 00:02:31,210 >> 不过,导致这个法医pset中,我们将介绍在pset4位的图形。 47 00:02:31,210 --> 00:02:35,410 你可能把这些东西是理所当然的 - JPEG格式,GIF和等 - 这些天。 48 00:02:35,410 --> 00:02:38,320 但如果你真的仔细想想,图像,就像罗布的脸, 49 00:02:38,320 --> 00:02:41,270 可以作为一个序列的点或像素建模。 50 00:02:41,270 --> 00:02:43,380 在罗布的脸的情况下,有各种颜色, 51 00:02:43,380 --> 00:02:46,760 我们开始看到各个点,否则称为像素, 52 00:02:46,760 --> 00:02:48,610 一旦我们开始放大。 53 00:02:48,610 --> 00:02:54,660 但是,如果我们简化了世界了一下,只是说,这是抢在黑色和白色, 54 00:02:54,660 --> 00:02:57,490 代表黑色和白色,我们可以只使用二进制文件。 55 00:02:57,490 --> 00:03:01,660 如果我们要使用二进制的1或0,我们可以表达这种相同的图像 56 00:03:01,660 --> 00:03:06,140 这种模式的位Rob的笑脸。 57 00:03:06,140 --> 00:03:12,100 11000011代表白,白,黑,黑,黑,黑,白,白。 58 00:03:12,100 --> 00:03:16,150 因此,它不是一个巨大的飞跃,然后开始谈论精美图片, 59 00:03:16,150 --> 00:03:18,600 的东西,你会看到在Facebook或用数码相机拍摄。 60 00:03:18,600 --> 00:03:21,410 但可以肯定的,当涉及到颜色,你需要更多的比特。 61 00:03:21,410 --> 00:03:25,690 在世界上的照片相当普遍的是使用1位颜色, 62 00:03:25,690 --> 00:03:29,560 因为这建议,但24位色,你实际上得到数百万种颜色。 63 00:03:29,560 --> 00:03:32,250 因此,作为的情况下,当我们放大罗布的眼睛上, 64 00:03:32,250 --> 00:03:36,370 这是任何数以百万计的不同颜色的可能性。 65 00:03:36,370 --> 00:03:39,040 因此,我们将介绍本习题集4,以及在演练中, 66 00:03:39,040 --> 00:03:43,370 这将是今天下午3:30,而不是平常的下午2时30分,因为上周五的演讲在这里。 67 00:03:43,370 --> 00:03:46,620 但是,视频将在网上像往常一样的明天。 68 00:03:46,620 --> 00:03:48,820 >> 我们还将为您介绍另一种文件格式。 69 00:03:48,820 --> 00:03:51,270 这是故意为了看起来吓人, 70 00:03:51,270 --> 00:03:55,670 但是,这仅仅是一些文件的C结构。 71 00:03:55,670 --> 00:03:58,940 事实证明,微软几年前捧红这种格式 72 00:03:58,940 --> 00:04:05,150 ,BMP的位图文件格式,这是一个超级简单的,丰富多彩的图形文件格式 73 00:04:05,150 --> 00:04:10,150 用于相当长的一段时间,有时还在桌面上的壁纸。 74 00:04:10,150 --> 00:04:14,760 如果你觉得回到了Windows XP和连绵起伏的丘陵和蓝色的天空, 75 00:04:14,760 --> 00:04:17,170 这是典型的bmp或位图图像。 76 00:04:17,170 --> 00:04:19,959 位图是我们的乐趣,因为他们有了更多的复杂性。 77 00:04:19,959 --> 00:04:22,610 这是不是很简单,因为这格的0和1。 78 00:04:22,610 --> 00:04:27,510 相反,你必须像一个头在一个文件的开始的东西。 79 00:04:27,510 --> 00:04:31,990 因此,在其他的话,里面的bmp文件是一大堆的0和1, 80 00:04:31,990 --> 00:04:34,910 但在那里有一些额外的“0”和“1。 81 00:04:34,910 --> 00:04:38,220 而事实证明,我们可能已经多年理所当然的 - 82 00:04:38,220 --> 00:04:45,170 任何文件格式的文件格式,如doc或xls或MP3,MP4, 83 00:04:45,170 --> 00:04:48,480 你是熟悉的 - 它甚至意味着是一种文件格式, 84 00:04:48,480 --> 00:04:52,480 因为在一天结束的时候,所有的这些文件,我们只有“0”和“1。 85 00:04:52,480 --> 00:04:56,810 也许那些“0”和“1代表ABC通过ASCII或类似的, 86 00:04:56,810 --> 00:04:58,820 但在一天结束的时候,它仍然只是“0”和“1。 87 00:04:58,820 --> 00:05:02,100 因此,人类只是偶尔决定发明一种新的文件格式 88 00:05:02,100 --> 00:05:06,420 他们规范的位模式,实际上的意思。 89 00:05:06,420 --> 00:05:09,220 在这种情况下,这里的人谁设计的位图文件格式 90 00:05:09,220 --> 00:05:15,620 说的第一个字节中的位图文件,有表示的偏移量为0, 91 00:05:15,620 --> 00:05:18,940 有一些神秘命名的变量称为bfType, 92 00:05:18,940 --> 00:05:23,080 这只是代表了位图文件的类型,这是什么类型的位图文件。 93 00:05:23,080 --> 00:05:27,700 你或许可以推断出从第二行偏移2字节2号, 94 00:05:27,700 --> 00:05:33,740 有图案的0和1,代表什么?事物的大小。 95 00:05:33,740 --> 00:05:35,310 它从那里。 96 00:05:35,310 --> 00:05:37,410 因此,在习题集4,你会走过一些事情。 97 00:05:37,410 --> 00:05:39,520 我们会关心所有的人都没有好下场。 98 00:05:39,520 --> 00:05:47,510 但是请注意,它开始变得有趣的周围字节54:rgbtBlue,绿色和红色。 99 00:05:47,510 --> 00:05:52,110 如果你曾经听说过的缩写,RGB - 红,绿,蓝 - 这是一个参考 100 00:05:52,110 --> 00:05:54,610 因为事实证明,你可以画的彩虹的所有颜色 101 00:05:54,610 --> 00:05:58,180 与红色,蓝色和绿色的某种组合。 102 00:05:58,180 --> 00:06:03,320 而事实上,在房间里的父母可能还记得最早的投影机。 103 00:06:03,320 --> 00:06:05,890 这些天,你只看到一个明亮的光出来的镜头, 104 00:06:05,890 --> 00:06:09,800 但早在一天,你有红色的镜片,蓝色镜片,绿色镜片, 105 00:06:09,800 --> 00:06:13,380 和一起,他们的目的是在屏幕上,并形成了丰富多彩的画面。 106 00:06:13,380 --> 00:06:16,270 很多时候,中学和高中有那些镜头 107 00:06:16,270 --> 00:06:19,720 有一点点歪,所以你看到双重或三重影像。 108 00:06:19,720 --> 00:06:24,100 但他的想法。你有红色,绿色和蓝色光画一幅画。 109 00:06:24,100 --> 00:06:26,590 在电脑上使用相同的原则。 110 00:06:26,590 --> 00:06:30,230 >> 所以之间的挑战,那么对你来说,在问题设置都将是几件事情。 111 00:06:30,230 --> 00:06:34,800 一个是调整图像的大小,图案中的0和1, 112 00:06:34,800 --> 00:06:40,200 找出其中的“0”和“1块代表什么这样的结构在, 113 00:06:40,200 --> 00:06:43,630 然后找出如何复制的像素 - 红军,蓝军,果岭 - 114 00:06:43,630 --> 00:06:46,660 内,这样当最初的图片看起来是这样的, 115 00:06:46,660 --> 00:06:49,210 它可能看起来像这样,而不是之后。 116 00:06:49,210 --> 00:06:53,640 在其他的挑战将是,你会交由法医的图像 117 00:06:53,640 --> 00:06:56,030 一个实际的文件从数码相机。 118 00:06:56,030 --> 00:06:58,960 该相机,曾几何时,是一大堆的照片。 119 00:06:58,960 --> 00:07:03,760 问题是我们不小心删除或已损坏的图像以某种方式。 120 00:07:03,760 --> 00:07:05,750 不好的事情发生的数码相机。 121 00:07:05,750 --> 00:07:09,150 所以我们很快就复制了所有为你关闭该卡的“0”和“1, 122 00:07:09,150 --> 00:07:13,610 保存他们都在一个大文件,然后我们会交给你的问题​​集4 123 00:07:13,610 --> 00:07:19,320 所以,你可以写一个程序,在C恢复所有的这些JPEG文件,理想。 124 00:07:19,320 --> 00:07:23,330 而事实证明,JPEG文件,即使它们是有点复杂的文件格式 - 125 00:07:23,330 --> 00:07:26,360 他们要复杂得多,这笑脸 - 126 00:07:26,360 --> 00:07:31,160 事实证明,每一个JPEG相同的模式0和1开始。 127 00:07:31,160 --> 00:07:35,630 所以,最终,一个while循环或循环或类似的, 128 00:07:35,630 --> 00:07:38,880 在此法医图像,你可以遍历所有的“0”和“1, 129 00:07:38,880 --> 00:07:43,150 每次你看到的特殊的模式,集规范中定义的问题, 130 00:07:43,150 --> 00:07:47,880 在这里,你可以假设,具有非常高的概率,开始的JPEG。 131 00:07:47,880 --> 00:07:51,230 而一旦当你发现相同的模式一定数量的字节 132 00:07:51,230 --> 00:07:55,430 或千字节或兆字节后,你可以假设这里是第二JPEG, 133 00:07:55,430 --> 00:07:57,380 我把照片后的第一个。 134 00:07:57,380 --> 00:08:01,370 让我停止阅读,第一个文件,开始写这个新的, 135 00:08:01,370 --> 00:08:06,310 输出你的程序pset4的是多达50个JPEG文件。 136 00:08:06,310 --> 00:08:09,270 而且,如果它不是50 JPEG文件,你有一点的循环。 137 00:08:09,270 --> 00:08:12,490 如果你有无限多的JPEG文件,你有一个无限循环。 138 00:08:12,490 --> 00:08:14,910 所以,这也将是一个相当常见的情况。 139 00:08:14,910 --> 00:08:16,600 所以,这就是在地平线上。 140 00:08:16,600 --> 00:08:21,310 >> 测验0在我们的身后,实现按我的电子邮件,总是有乡亲谁都是幸福的, 141 00:08:21,310 --> 00:08:23,640 排序的中性,悲伤周围测验的0时间。 142 00:08:23,640 --> 00:08:26,800 请你伸出我的头,你自己的TF TF Zamyla, 143 00:08:26,800 --> 00:08:31,180 的CA,你知道,如果你想讨论如何去。 144 00:08:31,180 --> 00:08:35,539 >> 因此,要在这里留下深刻印象的父母在房间里,什么是的CS50库吗? 145 00:08:36,429 --> 00:08:40,390 [笑声]好工作。 146 00:08:40,390 --> 00:08:48,340 的CS50库?是啊。 >> [学生]:这是一个预先写好的代码集[听不清] 147 00:08:48,340 --> 00:08:49,750 好,好。 148 00:08:49,750 --> 00:08:53,240 这是一个预先写好的代码集,我们的工作人员写的,我们提供给你, 149 00:08:53,240 --> 00:08:55,030 提供了一些常用的功能, 150 00:08:55,030 --> 00:08:59,020 这样的东西让我一个字符串,给我一个int - 此处列出的所有的功能。 151 00:08:59,020 --> 00:09:02,260 >> 从现在起,我们开始真正把这些训练车轮。 152 00:09:02,260 --> 00:09:05,050 我们将开始从你带走一个字符串, 153 00:09:05,050 --> 00:09:08,870 这使人想起什么实际的数据类型只是一个代名词? >> [多学生的char *。 154 00:09:08,870 --> 00:09:12,730 CHAR *。对于父母来说,那可能是[呼呼的声音。这是很好的。 155 00:09:12,730 --> 00:09:17,550 我们将开始看到在屏幕上更因为我们从我们的词汇中删除字符串的char *, 156 00:09:17,550 --> 00:09:19,730 至少当涉及到实际编写代码。 157 00:09:19,730 --> 00:09:22,840 同样,我们将停止使用这些功能尽可能多 158 00:09:22,840 --> 00:09:25,280 因为我们的程序将会变得更加复杂。 159 00:09:25,280 --> 00:09:28,480 而不是仅仅写一个提示,闪烁坐在那里, 160 00:09:28,480 --> 00:09:31,870 等待用户输入一些东西,你会得到你输入的其他地方。 161 00:09:31,870 --> 00:09:35,490 例如,你会得到他们的本地硬盘驱动器上的一系列位。 162 00:09:35,490 --> 00:09:38,580 相反,你会得到他们在未来的网络连接, 163 00:09:38,580 --> 00:09:40,230 一些网站的地方。 164 00:09:40,230 --> 00:09:44,110 >> 因此,让我们剥开这层第一次拉CS50电器 165 00:09:44,110 --> 00:09:49,010 这个文件称为cs50.h,#你已经包括了几个星期, 166 00:09:49,010 --> 00:09:51,140 但让我们看到这里面有什么。 167 00:09:51,140 --> 00:09:54,430 在蓝色的文件的顶部是一大堆的意见: 168 00:09:54,430 --> 00:09:57,050 保修信息和许可。 169 00:09:57,050 --> 00:09:59,050 这是一个共同的范式软件 170 00:09:59,050 --> 00:10:01,580 这些天,因为很多软件是所谓的开源的, 171 00:10:01,580 --> 00:10:05,220 这意味着有人已经写好的代码和自由 172 00:10:05,220 --> 00:10:10,470 不只是运行和使用,但实际读取和修改,并融入自己的工作。 173 00:10:10,470 --> 00:10:14,660 所以,这就是你一直在使用开源软件,尽管在一个非常小的形式。 174 00:10:14,660 --> 00:10:18,560 不过,如果我向下滚动过去的意见,我们将开始看到一些比较熟悉的东西。 175 00:10:18,560 --> 00:10:25,010 在顶部,cs50.h文件包括一大堆的头文件的通知。 176 00:10:25,010 --> 00:10:28,560 最重要的这些,我们还没有见过,但一个是熟悉的。 177 00:10:28,560 --> 00:10:32,270 这些我们看到,尽管是短暂的,迄今? >> [学生]标准库。 178 00:10:32,270 --> 00:10:35,810 是啊,标准库。 stdlib.h中的malloc。 179 00:10:35,810 --> 00:10:38,320 一旦我们开始谈论动态内存分配, 180 00:10:38,320 --> 00:10:41,650 我们会回来下周开始,包括该文件。 181 00:10:41,650 --> 00:10:46,640 事实证明,布尔和真假实际上并不存在在C本身 182 00:10:46,640 --> 00:10:49,440 除非你有这个文件在这里。 183 00:10:49,440 --> 00:10:52,710 我们已经好几个星期,得到了包括stdbool.h 184 00:10:52,710 --> 00:10:55,620 这样,您可以使用这个概念的一个布尔值,true或false。 185 00:10:55,620 --> 00:10:58,620 没有这一点,你就必须假的排序,并使用int 186 00:10:58,620 --> 00:11:02,610 只是任意假设0是假的,1是真实的。 187 00:11:02,610 --> 00:11:07,150 如果我们进一步向下滚动,在这里我们定义一个字符串。 188 00:11:07,150 --> 00:11:11,390 事实证明,我们已经说过,这颗星在哪里并不重要。 189 00:11:11,390 --> 00:11:13,720 你甚至可以有空间的限制。 190 00:11:13,720 --> 00:11:16,740 我们这学期一直在推动它,因为这明确 191 00:11:16,740 --> 00:11:18,620 明星做的类型, 192 00:11:18,620 --> 00:11:21,700 但实现一样普遍,如果没有一点更为常见, 193 00:11:21,700 --> 00:11:24,430 是把它放在那里,但在功能上是一样的东西。 194 00:11:24,430 --> 00:11:27,720 但现在如果我们进一步读下来,让我们来看看在调用getInt 195 00:11:27,720 --> 00:11:32,190 因为我们使用之前,也许别的学期。 196 00:11:32,190 --> 00:11:37,440 下面是调用getInt。这是什么? >> [学生]的原型。 >>这仅仅是一个原型。 197 00:11:37,440 --> 00:11:41,410 通常情况下,我们的原型在我们的顶部。c文件, 198 00:11:41,410 --> 00:11:46,690 但你也可以把原型的头文件,。h文件中,像这样的在这里 199 00:11:46,690 --> 00:11:50,840 所以,当你写一些功能,你希望其他人能够使用, 200 00:11:50,840 --> 00:11:53,550 而这恰恰与CS50库的情况下, 201 00:11:53,550 --> 00:11:57,040 你不仅实现你的功能的东西像cs50.c, 202 00:11:57,040 --> 00:12:02,790 也把原型不是在该文件的顶部,但在一个头文件的顶部。 203 00:12:02,790 --> 00:12:07,170 然后,头文件是什么样的朋友和同事,包括 204 00:12:07,170 --> 00:12:09,760 在自己的代码中使用#include。 205 00:12:09,760 --> 00:12:12,210 所以这个时候,你已经包括所有这些原型, 206 00:12:12,210 --> 00:12:16,580 在文件的开头,但通过这有效地#include机制, 207 00:12:16,580 --> 00:12:20,070 这基本上是复制和粘贴文件到您自己的。 208 00:12:20,070 --> 00:12:23,070 下面是一些比较详细的文档。 209 00:12:23,070 --> 00:12:25,640 我们几乎是理所当然的调用getInt得到一个int, 210 00:12:25,640 --> 00:12:27,640 但事实证明,有一些角落的情况下。 211 00:12:27,640 --> 00:12:31,810 如果用户键入的数字太大了,一百万的三次方, 212 00:12:31,810 --> 00:12:35,490 ,只是不能装进一个int?什么是预期的行为吗? 213 00:12:35,490 --> 00:12:38,020 理想的情况下,它是可预测的。 214 00:12:38,020 --> 00:12:40,280 因此,在这种情况下,如果你真正阅读印刷精美, 215 00:12:40,280 --> 00:12:44,500 实际上,你会看到,如果该行不能被读取,这将返回INT_MAX。 216 00:12:44,500 --> 00:12:48,320 我们从来没有提到这一点,但其资本额的基础上,它可能是什么? 217 00:12:48,320 --> 00:12:50,640 [学生]恒定的。 >>这是一个常数。 218 00:12:50,640 --> 00:12:54,770 这可能是这些头文件在一个声明,它的一些特殊的常量 219 00:12:54,770 --> 00:13:00,090 了更高的文件,并INT_MAX大概就像大约2亿美元, 220 00:13:00,090 --> 00:13:04,990 的想法是,因为我们需要以某种方式表明的东西出了问题, 221 00:13:04,990 --> 00:13:10,700 是的,我们有我们所掌握的4十亿的数字:-2亿元到2亿元,给予或采取。 222 00:13:10,700 --> 00:13:14,710 那么,什么是常见的编程是你偷的只是这些数字, 223 00:13:14,710 --> 00:13:18,920 也许0,也许2十亿,也许-2亿元, 224 00:13:18,920 --> 00:13:23,280 所以你用一个可能的值,这样就可以提交到世界 225 00:13:23,280 --> 00:13:26,820 ,如果出现错误,我会回到这个超级大的价值。 226 00:13:26,820 --> 00:13:31,030 但你不希望用户输入一些神秘的像234 ...,一个非常大的数字。 227 00:13:31,030 --> 00:13:34,060 您概括它,而不是为一个常数。 228 00:13:34,060 --> 00:13:38,060 所以,真的,如果你是肛门过去几周里,任何时候你叫调用getInt, 229 00:13:38,060 --> 00:13:42,900 你应该被检查,如果条件做了INT_MAX的用户类型, 230 00:13:42,900 --> 00:13:46,590 或者,更具体地说,调用getInt返回INT_MAX,因为如果它这样做, 231 00:13:46,590 --> 00:13:51,830 这实际上意味着他们没有键入它。在这种情况下,出现了错误。 232 00:13:51,830 --> 00:13:56,080 因此,这是通常被称为一个标记值,这只是意味着什么。 233 00:13:56,080 --> 00:13:58,120 >> 现在,让我们变成的。c文件。 234 00:13:58,120 --> 00:14:01,340 C文件已经存在了一段时间的家电。 235 00:14:01,340 --> 00:14:06,840 而事实上,该设备有预编译的到的事情,我们称为目标代码, 236 00:14:06,840 --> 00:14:09,540 但它只是对你重要,那是因为系统知道 237 00:14:09,540 --> 00:14:11,730 在这种情况下,它是:该设备。 238 00:14:11,730 --> 00:14:17,400 让我们现在向下滚动到调用getInt,看看如何调用getInt一直致力于这一切。 239 00:14:17,400 --> 00:14:19,460 在这里,我们从之前也有类似的评论。 240 00:14:19,460 --> 00:14:21,660 让我放大的代码部分。 241 00:14:21,660 --> 00:14:23,900 我们调用getInt如下。 242 00:14:23,900 --> 00:14:25,700 它不接受任何输入。 243 00:14:25,700 --> 00:14:29,510 它返回一个int值,而(真),所以我们有一个故意的无限循环, 244 00:14:29,510 --> 00:14:33,180 但想必大家会打破这个以某种方式或在此返回。 245 00:14:33,180 --> 00:14:34,870 >> 让我们来看看它是如何工作的。 246 00:14:34,870 --> 00:14:39,240 我们似乎在这个循环内的第一线,使用GetString 166。 247 00:14:39,240 --> 00:14:43,780 现在,这是很好的做法,因为在什么情况下可能的GetString返回 248 00:14:43,780 --> 00:14:47,660 特殊的关键字NULL? >> [学生]如果出现错误。 249 00:14:47,660 --> 00:14:51,630 如果出现错误。会出什么差错,当你调用类似的GetString? 250 00:14:54,960 --> 00:14:57,640 是啊。 >> [学生] malloc失败给它的整数。 251 00:14:57,640 --> 00:14:59,150 是啊。也许malloc失败。 252 00:14:59,150 --> 00:15:03,190 引擎盖下方的某个地方,GetString的调用malloc分配内存, 253 00:15:03,190 --> 00:15:06,020 这使得计算机能够存储所有的字符 254 00:15:06,020 --> 00:15:07,750 进入键盘的用户类型。 255 00:15:07,750 --> 00:15:11,590 假设用户得到了很多的空闲时间,多类型的,例如, 256 00:15:11,590 --> 00:15:16,160 甚至有超过2亿美元,比电脑更多的字符的字符RAM。 257 00:15:16,160 --> 00:15:19,250 GetString的是,以表示对你。 258 00:15:19,250 --> 00:15:22,560 即使这是一个超级,超级罕见的角落的情况, 259 00:15:22,560 --> 00:15:24,340 它以某种方式来处理这个问题, 260 00:15:24,340 --> 00:15:28,750 等GetString时,如果我们回去,并阅读其说明文件,确实在事实上,返回NULL。 261 00:15:28,750 --> 00:15:34,460 所以,现在如果GetString的失败,返回NULL,调用getInt是要失败的返回INT_MAX 262 00:15:34,460 --> 00:15:37,690 就像一个哨兵。这些都只是人的约定。 263 00:15:37,690 --> 00:15:41,450 你会知道这是唯一的办法是通过阅读文档。 264 00:15:41,450 --> 00:15:45,040 >> 让我们向下滚动到其中int实际上是得到了。 265 00:15:45,040 --> 00:15:51,160 如果我向下滚动一些,在170行,我们有上述评论,这些线路。 266 00:15:51,160 --> 00:15:55,100 我们声明一个int,N,和一个char,C,然后这个新的功能,在172 267 00:15:55,100 --> 00:15:58,930 你们中的一些偶然发现之前,sscanf的。 268 00:15:58,930 --> 00:16:00,870 这代表的字符串scanf函数。 269 00:16:00,870 --> 00:16:05,700 换句话说,给我一个字符串,我将扫描件信息感兴趣。 270 00:16:05,700 --> 00:16:07,360 这是什么意思呢? 271 00:16:07,360 --> 00:16:11,800 假设,我在键盘上输入,从字面上看,123,然后按Enter键。 272 00:16:11,800 --> 00:16:16,470 123时,由GetString返回的数据类型是什么? >> [学生]字符串。 273 00:16:16,470 --> 00:16:18,380 这显然​​是一个字符串,对不对?我有一个字符串。 274 00:16:18,380 --> 00:16:23,220 所以123是真的,报价引文结束,123 \ 0在它的结束。 275 00:16:23,220 --> 00:16:27,110 这不是一个整数。这不是一个数字。它看起来像一个数字,但它实际上不是。 276 00:16:27,110 --> 00:16:29,080 那么,是什么调用getInt有什么关系? 277 00:16:29,080 --> 00:16:35,750 从左向右扫描该字符串 - 123 \ 0 - ,并以某种方式转换成一个实际的整数。 278 00:16:35,750 --> 00:16:37,850 你可以计算出如何做到这一点。 279 00:16:37,850 --> 00:16:41,450 如果你觉得回到了pset2,你大概有点生气了舒适与凯撒 280 00:16:41,450 --> 00:16:44,820 或维琼内尔,所以你可以遍历字符串,你可以转换为整数的字符。 281 00:16:44,820 --> 00:16:46,710 不过,赫克说,这是一个大量的工作。 282 00:16:46,710 --> 00:16:49,860 sscanf的,做一个这样的函数,你为什么不叫? 283 00:16:49,860 --> 00:16:54,230 ,所以sscanf的预计参数 - 在这种情况下,称为线,它是一个字符串。 284 00:16:54,230 --> 00:17:01,840 然后,您可以指定在引号中,非常类似于printf,你希望看到在这个字符串中。 285 00:17:01,840 --> 00:17:09,000 我在这里所说的是我希望看到一个十进制数,也许一个字符。 286 00:17:09,000 --> 00:17:12,000 我们会看到为什么是这样的情况下,在短短的时刻。 287 00:17:12,000 --> 00:17:15,869 事实证明,这个符号是现在回忆的东西,我们开始谈论 288 00:17:15,869 --> 00:17:17,619 只是在一个星期前。 289 00:17:17,619 --> 00:17:21,740 什么是&N&C为我们做吗? >> [学生] n和c的地址。 290 00:17:21,740 --> 00:17:25,400 是啊。它给我的地址n和c的地址。为什么这很重要? 291 00:17:25,400 --> 00:17:30,220 你知道,在C的功能,您可以随时返回一个值或没有价值。 292 00:17:30,220 --> 00:17:34,530 您可以返回一个int,一个字符串,一个浮点数,字符,什么的,或者你可以返回void, 293 00:17:34,530 --> 00:17:38,030 但你可以只返回一件事最大限度。 294 00:17:38,030 --> 00:17:42,760 但在这里我们要sscanf的我,也许返回一个int,一个十进制数, 295 00:17:42,760 --> 00:17:46,220 和一个字符,在某一时刻,我会解释为什么字符。 296 00:17:46,220 --> 00:17:51,460 您可以有效地sscanf函数返回两件事情,但是这只是不可能在C. 297 00:17:51,460 --> 00:17:55,200 您可以解决的,通过两个地址 298 00:17:55,200 --> 00:17:57,370 因为只要你交给一个功能的两个地址, 299 00:17:57,370 --> 00:18:00,470 该函数有什么可以做呢? >> [学生]发表到这些地址。 300 00:18:00,470 --> 00:18:02,010 它可以写入到这些地址。 301 00:18:02,010 --> 00:18:05,770 您可以使用恒星运转,去那里,每个地址。 302 00:18:05,770 --> 00:18:11,260 用于改变的变量的值,它的排序这个后门的机制,但很常见的 303 00:18:11,260 --> 00:18:14,870 以上只是一个地方 - 在这种情况下,两个。 304 00:18:14,870 --> 00:18:21,340 请注意,我检查== 1,然后返回n如果这样做,其实,计算结果为true。 305 00:18:21,340 --> 00:18:26,170 所以,这是怎么回事呢?从技术上说,我们真的要发生在调用getInt是这样的。 306 00:18:26,170 --> 00:18:30,740 我们要分析,可以这么说,我们要读取的字符串 - 报价 - 享有的123 - 307 00:18:30,740 --> 00:18:34,560 如果它看起来像有一个数字,则我们告诉sscanf的做 308 00:18:34,560 --> 00:18:38,190 在这个变量n对我来说,这个数字 - 123 - 。 309 00:18:38,190 --> 00:18:42,090 那么为什么我居然有这样的呢? 310 00:18:42,090 --> 00:18:48,220 sscanf的说你可能会得到一个字符在这里的作用是什么? 311 00:18:48,220 --> 00:18:53,470 [听不见的学生反应] >> A小数点实际上可以工作。 312 00:18:53,470 --> 00:18:56,330 让我们认为,想了一会儿。还有什么呢? 313 00:18:56,330 --> 00:18:59,270 [学生]:这可能是NULL。 >>良好的思想。这可能是空字符。 314 00:18:59,270 --> 00:19:01,660 在这种情况下,它实际上不是。是啊。 >> [学生] ASCII。 315 00:19:01,660 --> 00:19:04,340 ASCII。还是让我进一步概括。 316 00:19:04,340 --> 00:19:06,640 %c有错误检查。 317 00:19:06,640 --> 00:19:09,300 我们不希望这是之后的字符数, 318 00:19:09,300 --> 00:19:11,870 但让我做的是以下。 319 00:19:11,870 --> 00:19:18,210 事实证明,sscanf的,除了这里存储在n和c的值,在这个例子中, 320 00:19:18,210 --> 00:19:24,890 什么也没有返回的变量值英寸 321 00:19:24,890 --> 00:19:30,260 所以,如果你只输入了123,那么只有%是怎么回事相匹配, 322 00:19:30,260 --> 00:19:33,880 只有n个被存储的值,如123, 323 00:19:33,880 --> 00:19:35,640 没有东西在c。 324 00:19:35,640 --> 00:19:37,620 C保持一个垃圾值,可以这么说 - 325 00:19:37,620 --> 00:19:40,730 垃圾,因为它从来没有被初始化为某个值。 326 00:19:40,730 --> 00:19:45,520 因此,在这种情况下,sscanf函数返回1,因为我填充这些指针, 327 00:19:45,520 --> 00:19:50,190 在这种情况下,伟大的,我有一个int,所以我释放线释放内存 328 00:19:50,190 --> 00:19:54,000 实际上,GetString的分配,然后我返回n, 329 00:19:54,000 --> 00:19:58,500 否则,如果你有没有想过,重试来自,它来自这里。 330 00:19:58,500 --> 00:20:04,390 这样的话,与此相反,I型123foo - 只是一些随机序列的文本 - 331 00:20:04,390 --> 00:20:08,490 ,sscanf的是要看到数字,数字,数,f, 332 00:20:08,490 --> 00:20:16,410 和它打算把n的123,它打算把在c在f,然后返回2。 333 00:20:16,410 --> 00:20:20,640 因此,我们有,只是使用的基本定义,sscanf的行为,一个很简单的方法 - 334 00:20:20,640 --> 00:20:23,900 以及,复杂,乍一看,但在年底的一天相当简单的机制 - 335 00:20:23,900 --> 00:20:28,320 说的是有一个int,如果是的话,是我发现的唯一吗? 336 00:20:28,320 --> 00:20:29,860 这里的空白是故意的。 337 00:20:29,860 --> 00:20:34,000 如果你读了sscanf的文档,它会告诉你,如果你有一块空白 338 00:20:34,000 --> 00:20:38,810 在开端或末端,sscanf的太将允许用户,无论什么原因, 339 00:20:38,810 --> 00:20:41,860 按空格键123,这将是合法的。 340 00:20:41,860 --> 00:20:44,150 你不会在用户喊叫,只是因为他们打空格键 341 00:20:44,150 --> 00:20:48,640 在开始或结束,这只是一个小更方便用户使用。 342 00:20:48,640 --> 00:20:52,300 >> 如有任何问题,然后调用getInt?是啊。 >> [学生]如果你只是把一个char是什么? 343 00:20:52,300 --> 00:20:54,030 这个问题问得好。 344 00:20:54,030 --> 00:20:59,890 如果你刚刚输入的一个字符像f,并按下回车键没有输入123,该怎么办? 345 00:20:59,890 --> 00:21:02,420 你认为这行代码的行为将是什么? 346 00:21:02,420 --> 00:21:04,730 [听不见的学生反应] 347 00:21:04,730 --> 00:21:08,790 是啊,所以sscanf的可以覆盖这一点,因为在这种情况下,它不会填写N或C。 348 00:21:08,790 --> 00:21:15,310 这是怎么回事,而不是返回0,在这种情况下,我也赶上该方案 349 00:21:15,310 --> 00:21:18,750 我想是因为预期值1。 350 00:21:18,750 --> 00:21:22,000 我只想要一个只有一件事来填补。这个问题问得好。 351 00:21:22,000 --> 00:21:24,290 >> 其他人吗?好的。 352 00:21:24,290 --> 00:21:26,250 >> 让我们通过在这里的所有的功能, 353 00:21:26,250 --> 00:21:29,500 但是,这似乎是可能的剩余权益的GetString 354 00:21:29,500 --> 00:21:32,790 因为事实证明调用getInt GetFloat,的GetDouble,GetLongLong 355 00:21:32,790 --> 00:21:36,260 所有平底船了很多的功能,GetString的。 356 00:21:36,260 --> 00:21:39,750 因此,让我们来看看他是如何在这里实现。 357 00:21:39,750 --> 00:21:43,630 这一个看起来有点复杂,但它使用相同的基本原理 358 00:21:43,630 --> 00:21:45,670 我们开始谈论上周。 359 00:21:45,670 --> 00:21:49,490 GetString时,它没有参数,在这里每虚空 360 00:21:49,490 --> 00:21:53,730 它返回一个字符串,我显然我声明了字符串缓冲。 361 00:21:53,730 --> 00:21:56,270 我真的不知道那是什么要用于还,但我们会看到。 362 00:21:56,270 --> 00:21:58,390 它看起来像能力是由默认的0。 363 00:21:58,390 --> 00:22:01,350 不太清楚这是怎么回事,不知道n是要用于还 364 00:22:01,350 --> 00:22:03,590 但现在它变得更有趣一些。 365 00:22:03,590 --> 00:22:06,520 在243行,我们声明了一个int,C。 366 00:22:06,520 --> 00:22:08,800 这是一个愚蠢的细节。 367 00:22:08,800 --> 00:22:15,820 char是8位,8位可以存储多少不同的值吗? >> [学生256。 >> 256。 368 00:22:15,820 --> 00:22:20,730 现在的问题是,如果你想有256个不同的ASCII字符,其中有 369 00:22:20,730 --> 00:22:23,340 如果你认为 - 这是不是记住的东西。 370 00:22:23,340 --> 00:22:25,710 但是,如果你觉得回到了那个大的ASCII图表,我们有几个星期前, 371 00:22:25,710 --> 00:22:30,600 在这种情况下,有128或256个ASCII字符。 372 00:22:30,600 --> 00:22:32,940 我们使用所有的模式,“0”和“1了。 373 00:22:32,940 --> 00:22:36,210 这是一个问题,如果你想成为能够检测到一个错误 374 00:22:36,210 --> 00:22:40,190 因为如果你已经使用了256个值,为你的角色, 375 00:22:40,190 --> 00:22:43,050 你真的不提前计划,因为现在你也没有办法说, 376 00:22:43,050 --> 00:22:46,270 这是不是一个合法的字符,这是一些错误的信息。 377 00:22:46,270 --> 00:22:50,270 所以,世界是他们最大的价值,像一个int, 378 00:22:50,270 --> 00:22:54,720 所以,你有一个疯狂的数字,32位,4亿的可能值 379 00:22:54,720 --> 00:22:58,860 所以,你可以简单的使用基本上是257, 380 00:22:58,860 --> 00:23:01,720 1,其中有一些特殊的含义为错误。 381 00:23:01,720 --> 00:23:03,120 >> 因此,让我们来看看它是如何工作的。 382 00:23:03,120 --> 00:23:07,760 在246行,我有这样大的while循环,调用fgetc函数, 383 00:23:07,760 --> 00:23:11,090 F含义的文件,所以GETC,然后标准输入。 384 00:23:11,090 --> 00:23:15,520 事实证明,这仅仅是说从键盘读取输入更精确的方法。 385 00:23:15,520 --> 00:23:19,300 标准输入方式键盘,标准输出屏幕, 386 00:23:19,300 --> 00:23:23,310 和标准错误,我们会看到pset4的,就是说屏幕 387 00:23:23,310 --> 00:23:27,490 而是一种特殊的屏幕部分,因此,它不是与实际产量混为一谈 388 00:23:27,490 --> 00:23:30,750 你打算打印。但更多的是在未来。 389 00:23:30,750 --> 00:23:34,440 因此fgetc函数从键盘读取一个字符,并将其存储在那里? 390 00:23:34,440 --> 00:23:37,350 将它保存在c。 391 00:23:37,350 --> 00:23:41,360 然后再检查 - 所以我只是用一些布尔连词 - 392 00:23:41,360 --> 00:23:46,000 检查它不等于“ - \ n,所以在用户按下回车键,我们要停止在这一点上, 393 00:23:46,000 --> 00:23:49,850 循环结束 - 我们还需要检查的特殊常量EOF, 394 00:23:49,850 --> 00:23:53,610 如果你知道或猜测,什么是代表? >> [学生]:文件的末尾。 >>末页的文件。 395 00:23:53,610 --> 00:23:56,560 这是一种荒谬的,因为如果我在键盘上打字, 396 00:23:56,560 --> 00:23:58,870 真的没有参与这一文件, 397 00:23:58,870 --> 00:24:01,150 但是,这仅仅是排序的通用术语,用来指 398 00:24:01,150 --> 00:24:04,220 ,没有别的来自人类的手指。 399 00:24:04,220 --> 00:24:06,460 EOF - 文件结束。 400 00:24:06,460 --> 00:24:09,920 顺便说一句,如果你曾经打你的键盘控制D,不,你还没有 - 401 00:24:09,920 --> 00:24:15,230 你按下Control C - D发送控制这个特殊的常数,称为EOF。 402 00:24:15,230 --> 00:24:19,850 所以,现在我们只是有一些动态内存分配。 403 00:24:19,850 --> 00:24:23,440 >> 所以,如果第(n + 1>容量)。现在我将解释N。 404 00:24:23,440 --> 00:24:26,100 N是目前究竟有多少字节在缓冲区中, 405 00:24:26,100 --> 00:24:28,620 你目前正在建设的字符串从用户。 406 00:24:28,620 --> 00:24:33,450 如果你有比你有更多的字符在缓冲区中的缓冲能力, 407 00:24:33,450 --> 00:24:37,410 直观地,我们需要做的是什么,然后分配更多的容量。 408 00:24:37,410 --> 00:24:43,330 所以我要掠过这里的算术只专注于这个功能。 409 00:24:43,330 --> 00:24:46,070 你知道什么是malloc的,或至少是一般熟悉。 410 00:24:46,070 --> 00:24:48,970 什么realloc的猜测。 >> [学生]添加内存。 411 00:24:48,970 --> 00:24:52,920 这不是很新增记忆体。它重新分配的内存如下。 412 00:24:52,920 --> 00:24:57,220 如果在字符串的结尾还是有空间,该内存以使您更 413 00:24:57,220 --> 00:25:00,000 比原来给你,然后你会得到额外的内存。 414 00:25:00,000 --> 00:25:03,460 所以,你可以不断地将字符串的字符背靠背背靠背。 415 00:25:03,460 --> 00:25:05,830 但是,如果是这样的情况并非如此,因为你等太久 416 00:25:05,830 --> 00:25:07,940 和一些随机得到了一屁股在内存中 417 00:25:07,940 --> 00:25:10,290 但有额外的内存在这儿,没关系。 418 00:25:10,290 --> 00:25:13,100 realloc是要为你做所有的繁重, 419 00:25:13,100 --> 00:25:16,750 移动您已经阅读因而在离这里不远的字符串,把它放在那里, 420 00:25:16,750 --> 00:25:19,460 然后给你一些更多的在这一点上跑道。 421 00:25:19,460 --> 00:25:22,550 >> 因此,一挥手,让我说,是做什么的GetString 422 00:25:22,550 --> 00:25:26,330 是它的一个小缓冲区,也许一个单一的字符, 423 00:25:26,330 --> 00:25:30,820 如果两个字符的用户类型,GetString的最终调用realloc的,并说 424 00:25:30,820 --> 00:25:33,150 一个字符是不够的,给我两个字符。 425 00:25:33,150 --> 00:25:35,950 然后,如果你读通过逻辑的循环,它会说 426 00:25:35,950 --> 00:25:39,600 用户输入3个字符;给我,而不是2 4个字符, 427 00:25:39,600 --> 00:25:42,320 然后给我,然后给我16位和32位。 428 00:25:42,320 --> 00:25:45,000 事实上,我的能力增加一倍 429 00:25:45,000 --> 00:25:48,570 意味着该缓冲区不会生长缓慢,它的超快速增长。 430 00:25:48,570 --> 00:25:51,380 可能是什么的优势是什么? 431 00:25:51,380 --> 00:25:54,600 为什么我的缓冲区大小增加一倍 432 00:25:54,600 --> 00:25:58,020 即使用户可能只需要一个额外的字符从键盘吗? 433 00:25:58,020 --> 00:26:01,750 [听不见的学生回应] >>那是什么? >> [学生]你不经常必须增加。 434 00:26:01,750 --> 00:26:03,300 没错。您不必经常增长。 435 00:26:03,300 --> 00:26:05,510 而这仅仅是种对冲你的赌注在这里, 436 00:26:05,510 --> 00:26:10,850 的想法是,你不希望调用realloc的有很多,因为它往往是缓慢的。 437 00:26:10,850 --> 00:26:12,910 任何时候,你问的操作系统的内存, 438 00:26:12,910 --> 00:26:16,990 你很快就会看到在未来的习题集,它往往需要一定的时间。 439 00:26:16,990 --> 00:26:20,010 因此,最大限度地减少,大量的时间,即使你浪费了一些空间, 440 00:26:20,010 --> 00:26:21,900 往往是一个很好的事情。 441 00:26:21,900 --> 00:26:24,060 >> 但是,如果我们读通过的GetString在这里的最后一部分 - 442 00:26:24,060 --> 00:26:27,950 重新认识这里的每一行是不那么重要的今天 - 443 00:26:27,950 --> 00:26:30,530 注意,它最终再次调用malloc 444 00:26:30,530 --> 00:26:33,880 它分配完全一样,因为它需要多少个字节的字符串 445 00:26:33,880 --> 00:26:38,060 然后扔掉致电免费过大的缓冲区 446 00:26:38,060 --> 00:26:40,080 如果它确实得到了太多的时间翻了一倍。 447 00:26:40,080 --> 00:26:42,730 因此,在短,这是多么的GetString已工作时间。 448 00:26:42,730 --> 00:26:47,060 它所做的就是读取一个字符的时候,一而再,再而三, 449 00:26:47,060 --> 00:26:50,750 每次它需要一些额外的内存,它要求操作系统 450 00:26:50,750 --> 00:26:53,670 通过调用realloc的。 451 00:26:53,670 --> 00:26:57,890 >> 有什么问题吗?好的。 452 00:26:57,890 --> 00:26:59,270 >> 的攻击。 453 00:26:59,270 --> 00:27:04,060 现在,我们理解指针,或者至少是越来越熟悉指针, 454 00:27:04,060 --> 00:27:06,700 让我们考虑如何在整个世界开始崩溃 455 00:27:06,700 --> 00:27:10,030 如果你不太捍卫对对抗性用户, 456 00:27:10,030 --> 00:27:11,850 人们正试图攻入你的系统, 457 00:27:11,850 --> 00:27:16,890 人谁是试图窃取您的软件绕过一些注册码 458 00:27:16,890 --> 00:27:19,090 否则,他们可能有输入英寸 459 00:27:19,090 --> 00:27:22,990 >> 在这个例子来看看这里,这是C代码的底部,有一个main函数的 460 00:27:22,990 --> 00:27:26,380 调用一个函数foo。又是什么呢传递给foo? 461 00:27:26,380 --> 00:27:29,680 [学生]一个参数。 >> [马兰]的单个参数。 462 00:27:29,680 --> 00:27:33,450 因此,ARGV [1],这意味着用户在命令行中输入的第一个字 463 00:27:33,450 --> 00:27:36,360 后a.out或其他程序调用。 464 00:27:36,360 --> 00:27:41,680 所以foo的顶部需要一个char *。但char *是什么? >> [学生]一个字符串。 465 00:27:41,680 --> 00:27:43,350 [马兰]一个字符串,因此在这里没有什么新东西。 466 00:27:43,350 --> 00:27:45,420 该字符串是任意被称为酒吧。 467 00:27:45,420 --> 00:27:51,430 在这里,字符c [12];类的半技术性的英语,这条线是在做什么? 468 00:27:51,430 --> 00:27:55,220 [学生]的数组 - >>阵? >> [学生]字符。 >>字符。 469 00:27:55,220 --> 00:27:58,870 给我一个阵列为12个字符。因此,我们可以称之为一个缓冲。 470 00:27:58,870 --> 00:28:02,920 它在技术上被称为C,但程序中的缓冲区仅仅意味着一堆的空间 471 00:28:02,920 --> 00:28:04,800 你可以把一些东西英寸 472 00:28:04,800 --> 00:28:07,940 然后,最后,memcpy的,我们还没有使用过的,但你可能已经猜到它做什么。 473 00:28:07,940 --> 00:28:10,480 它的内存复制。它有什么作用呢? 474 00:28:10,480 --> 00:28:19,270 显然复制酒吧,它的输入,到c的长度吧。 475 00:28:19,270 --> 00:28:24,930 但有一个错误在这里。 >> [学生]您需要的sizeof字符。 “好了。 476 00:28:24,930 --> 00:28:30,860 从技术上讲,我们真的应该做的strlen(条)* sizeof(char)的)的。这是正确的。 477 00:28:30,860 --> 00:28:33,930 但是,在这里的最坏的情况下,让我们假定that's - 478 00:28:33,930 --> 00:28:35,950 好吧。然后有两个错误。 479 00:28:35,950 --> 00:28:39,160 大小(字符)); 480 00:28:39,160 --> 00:28:41,290 让我们使这一点更广泛。 481 00:28:41,290 --> 00:28:44,910 所以现在仍然是一个错误,这是什么? >> [听不见的学生反应] 482 00:28:44,910 --> 00:28:46,990 检查什么呢? >> [学生]检查是否为NULL。 483 00:28:46,990 --> 00:28:50,270 一般应检查是否为NULL,因为不好的事情发生 484 00:28:50,270 --> 00:28:53,200 当指针为NULL,因为你可能最终会去那里, 485 00:28:53,200 --> 00:28:57,630 你应该不会去提领的星算为NULL。 486 00:28:57,630 --> 00:29:01,050 所以这是很好的。而我们做什么?从逻辑上讲,在这里有一个缺陷。 487 00:29:01,050 --> 00:29:04,450 [学生]检查,如果argc> = 2。 488 00:29:04,450 --> 00:29:10,550 因此,检查,如果argc> = 2。好了,所以在这个程序有三个错误这里。 489 00:29:10,550 --> 00:29:16,630 我们现在会检查,如果用户实际键入任何东西到argv [1]。好。 490 00:29:16,630 --> 00:29:20,950 那么什么是第三个错误吗?是啊。 >> [学生] C可能没有足够大。 491 00:29:20,950 --> 00:29:23,320 好。我们检查一个场景。 492 00:29:23,320 --> 00:29:29,520 隐式检查,请不要复制更多的内存比将超过该长度的酒吧。 493 00:29:29,520 --> 00:29:32,510 因此,如果字符串用户输入的长度为10个字符, 494 00:29:32,510 --> 00:29:36,020 这是说只复制10个字符。没关系。 495 00:29:36,020 --> 00:29:39,940 但是,如果用户键入20个字符的字一个字的提示一样吗? 496 00:29:39,940 --> 00:29:44,900 这是说拷贝20个字符酒吧变成了什么? 497 00:29:44,900 --> 00:29:49,750 C,否则被称为我们的缓冲区,这意味着你只是写数据 498 00:29:49,750 --> 00:29:52,540 8个字节,你没有自己的位置, 499 00:29:52,540 --> 00:29:54,870 你并不拥有它们在这个意义上,你永远不分配。 500 00:29:54,870 --> 00:30:00,370 因此,这是一般人都知道的缓冲区溢出攻击缓冲区溢出攻击。 501 00:30:00,370 --> 00:30:05,580 在这个意义上,它是一个攻击,如果用户或程序的调用你的函数 502 00:30:05,580 --> 00:30:10,490 这样做恶意,实际情况下,实际上可能是相当糟糕的。 503 00:30:10,490 --> 00:30:12,450 >> 因此,让我们来看看这张照片。 504 00:30:12,450 --> 00:30:16,060 此图片代表你的内存堆栈。 505 00:30:16,060 --> 00:30:19,580 回想一下,每次你调用一个函数,你这个小的堆栈帧 506 00:30:19,580 --> 00:30:21,520 然后另一个,然后另一个和另一个。 507 00:30:21,520 --> 00:30:24,300 因此,到目前为止,我们只是一种抽象的这些矩形 508 00:30:24,300 --> 00:30:26,290 在黑板上,或在屏幕上这里。 509 00:30:26,290 --> 00:30:30,580 但是,如果我们放大这些矩形,当你调用一个函数foo, 510 00:30:30,580 --> 00:30:35,880 事实证明,更重要的是在栈上,框架内的在该矩形 511 00:30:35,880 --> 00:30:40,060 比是x和y,a和b,就像我们谈论交换。 512 00:30:40,060 --> 00:30:44,410 事实证明,有一些低级别的细节,其中包括返回地址。 513 00:30:44,410 --> 00:30:49,550 因此,原来当主调用foo,主要有告知富 514 00:30:49,550 --> 00:30:53,520 main()的地址是在计算机的内存中 515 00:30:53,520 --> 00:30:57,770 因为否则,尽快foo的完成,在这种情况下,在这里,执行 516 00:30:57,770 --> 00:31:00,830 一旦你达到这个封闭的大括号结束时的foo, 517 00:31:00,830 --> 00:31:05,310 富不知道如何赫克控制的程序是应该去吗? 518 00:31:05,310 --> 00:31:08,970 事实证明,这个问题的答案是在这个红色矩形。 519 00:31:08,970 --> 00:31:12,670 这是一个指针,它是电脑临时存储 520 00:31:12,670 --> 00:31:17,030 所谓的堆叠上的主地址,以便尽快为foo执行完成, 521 00:31:17,030 --> 00:31:21,120 电脑知道在哪里和什么线主要回去。 522 00:31:21,120 --> 00:31:23,940 保存的帧指针涉及此同样。 523 00:31:23,940 --> 00:31:26,310 CHAR *酒吧代表着什么? 524 00:31:26,310 --> 00:31:31,350 现在这个蓝色的部分是foo的框架。什么是吧? 525 00:31:31,570 --> 00:31:35,010 酒吧的foo函数的参数。 526 00:31:35,010 --> 00:31:37,500 所以,现在我们又回到熟悉的画面在排序。 527 00:31:37,500 --> 00:31:39,850 还有更多的东西,并在屏幕上的干扰, 528 00:31:39,850 --> 00:31:43,380 但这种淡蓝色的部分恰恰是我们一直在画在黑板上 529 00:31:43,380 --> 00:31:45,790 类似交换。这是为foo的框架。 530 00:31:45,790 --> 00:31:51,490 唯一在它现在是吧,这是此参数。 531 00:31:51,490 --> 00:31:55,220 还有什么应该是在堆栈中,根据此代码在这里? 532 00:31:55,220 --> 00:31:57,760 [学生]字符c [12]。 >> [马兰字符c [12]。 533 00:31:57,760 --> 00:32:02,810 我们也应该看到,12平方的内存分配给一个变​​量名为c, 534 00:32:02,810 --> 00:32:04,970 而事实上,我们也有在屏幕上。 535 00:32:04,970 --> 00:32:08,480 最顶端的是c [0],然后这张图的作者 536 00:32:08,480 --> 00:32:11,850 没有理会绘制所有的平方,但确实有12有 537 00:32:11,850 --> 00:32:16,590 因为,如果你看一下在右下角,C [11]如果从0数是12这样的字节。 538 00:32:16,590 --> 00:32:18,400 但这里的问题。 539 00:32:18,400 --> 00:32:22,390 在哪个方向是C成长? 540 00:32:22,390 --> 00:32:27,080 自上而下的,如果它开始的顶部和底部生长的排序。 541 00:32:27,080 --> 00:32:30,110 它看起来并不像我们给自己多跑道在这里。 542 00:32:30,110 --> 00:32:32,090 我们画种自己陷入了困境, 543 00:32:32,090 --> 00:32:36,940 C [11]是正确的,对吧,这是对保存的帧指针, 544 00:32:36,940 --> 00:32:39,960 这是正确的,对返回地址。有没有更多的空间。 545 00:32:39,960 --> 00:32:42,810 那么,有什么含义,然后如果你搞砸了 546 00:32:42,810 --> 00:32:46,500 您尝试读取20字节到12个字节的缓冲区? 547 00:32:46,500 --> 00:32:50,060 这8个额外的字节哪里去了? >> [学生]内 - 548 00:32:50,060 --> 00:32:53,200 一切里面,其中有一些是超级重要的。 549 00:32:53,200 --> 00:32:57,260 和最重要的事情,可能是那里的红色框,返回地址, 550 00:32:57,260 --> 00:33:03,560 因为假设你是意外或adversarially的覆盖这4个字节, 551 00:33:03,560 --> 00:33:07,260 该指针的地址,不只是垃圾,但有一些 552 00:33:07,260 --> 00:33:09,810 发生这种情况表示在内存中的实际地址。 553 00:33:09,810 --> 00:33:13,880 有何重要意义,逻辑吗? >> [学生]函数将返回一个不同的地方。 554 00:33:13,880 --> 00:33:15,250 没错。 555 00:33:15,250 --> 00:33:19,170 当foo回报率和点击率,大括号,程序将继续进行 556 00:33:19,170 --> 00:33:25,060 返回到主,它会返回的地址是在这红色框。 557 00:33:25,060 --> 00:33:28,600 >> 在绕过软件登记的情况下, 558 00:33:28,600 --> 00:33:32,260 什么如果返回到地址的功能,通常被称为 559 00:33:32,260 --> 00:33:35,690 后,你支付的软件,输入你的注册码? 560 00:33:35,690 --> 00:33:39,870 您可以按招的电脑不会在这里,而是在这里。 561 00:33:39,870 --> 00:33:45,100 或者,如果你真的很聪明,对手实际上可以输入在键盘上,例如, 562 00:33:45,100 --> 00:33:50,690 而不是实际的单词,而不是20个字符,但假设他或她居然类型 563 00:33:50,690 --> 00:33:52,770 一些字符表示代码。 564 00:33:52,770 --> 00:33:55,320 它不会是C代码,它实际上是字符 565 00:33:55,320 --> 00:33:59,290 代表二进制机器代码,“0”和“1。 566 00:33:59,290 --> 00:34:01,290 但是,假如他们足够聪明,要做到这一点, 567 00:34:01,290 --> 00:34:06,500 以某种方式粘贴到GetString的的提示东西,基本上是编译后的代码, 568 00:34:06,500 --> 00:34:09,980 最后4个字节,返回地址覆盖。 569 00:34:09,980 --> 00:34:13,360 请问您的地址,输入怎么办? 570 00:34:13,360 --> 00:34:18,630 它实际上是存储在这个红色矩形的缓冲区的第一个字节的地址。 571 00:34:18,630 --> 00:34:23,070 所以,你必须是真聪明,这是一个很大的试验和错误不好的人,在那里, 572 00:34:23,070 --> 00:34:25,639 但如果你能有多大,这个缓冲区 573 00:34:25,639 --> 00:34:28,820 最后几个字节的输入您提供的程序 574 00:34:28,820 --> 00:34:33,540 发生在开始您的缓冲区的地址,你可以做到这一点。 575 00:34:33,540 --> 00:34:39,320 如果我们通常所说的招呼,\ 0,这就是在缓冲区。 576 00:34:39,320 --> 00:34:44,420 但是,如果我们更聪明,我们填补了这一缓冲,我们将统称叫什么攻击代码 - 577 00:34:44,420 --> 00:34:48,860 AAA,攻击,攻击,攻击 - 这是只是做了一件坏事, 578 00:34:48,860 --> 00:34:51,820 如果你真的很聪明,会发生什么情况,你可能做到这一点。 579 00:34:51,820 --> 00:34:58,610 在这里的红色框是一个数字序列 - 80,C0,35,08。 580 00:34:58,610 --> 00:35:01,610 请注意,相匹配的数字在这里。 581 00:35:01,610 --> 00:35:04,430 它以相反的顺序,但其他一些时间。 582 00:35:04,430 --> 00:35:08,140 请注意,这个返回地址被故意改变 583 00:35:08,140 --> 00:35:12,020 相同的地址,而不是主要的地址。 584 00:35:12,020 --> 00:35:17,500 因此,如果坏家伙是超级聪明,他或她将要包括在该攻击代码 585 00:35:17,500 --> 00:35:20,930 像删除所有用户的文件或复制的密码 586 00:35:20,930 --> 00:35:24,680 或创建一个用户帐户,然后我就可以登录到 - 在所有事情。 587 00:35:24,680 --> 00:35:26,950 >> 这是危险的力量C. 588 00:35:26,950 --> 00:35:29,840 因为你必须通过指针存取记忆体 589 00:35:29,840 --> 00:35:32,520 因此,你可以写任何你想要到一台计算机的内存中, 590 00:35:32,520 --> 00:35:35,080 你可以让一台计算机做任何你想要的 591 00:35:35,080 --> 00:35:39,550 简单的跳跃,在它自己的内存空间。 592 00:35:39,550 --> 00:35:44,650 所以到今天这么多的程序和这么多的网站被攻破 593 00:35:44,650 --> 00:35:46,200 归结到人趁着这个。 594 00:35:46,200 --> 00:35:50,760 这可能看起来像一个超级复杂的攻击,但它并不总是这种方式开始。 595 00:35:50,760 --> 00:35:53,560 现实情况是,什么不好的人通常会做的是, 596 00:35:53,560 --> 00:35:58,200 无论它是一个程序,在命令行或GUI程序或网站, 597 00:35:58,200 --> 00:35:59,940 你刚开始提供废话。 598 00:35:59,940 --> 00:36:03,980 您键入一个真正的大词在搜索字段并按下回车键, 599 00:36:03,980 --> 00:36:05,780 你就等着看,如果网站崩溃 600 00:36:05,780 --> 00:36:09,990 或者你就等着看,如果程序体现了一些错误信息 601 00:36:09,990 --> 00:36:14,330 因为如果你幸运的坏家伙,你提供一些疯狂的输入 602 00:36:14,330 --> 00:36:18,980 ,导致程序崩溃,这意味着程序员没有预料到你的错误行为, 603 00:36:18,980 --> 00:36:23,630 这意味着你可以有足够的精力,足够的试验和错误, 604 00:36:23,630 --> 00:36:26,650 如何发动更精确的攻击。 605 00:36:26,650 --> 00:36:31,410 因此,安全的一部分,不只是完全避免这些攻击 606 00:36:31,410 --> 00:36:34,100 但检测,实际上是在寻找日志 607 00:36:34,100 --> 00:36:36,780 并看到什么疯狂的输入输入到你的网站的人, 608 00:36:36,780 --> 00:36:38,960 什么样的搜索字词输入到您的网站的人 609 00:36:38,960 --> 00:36:42,870 在一定的缓冲溢出的希望。 610 00:36:42,870 --> 00:36:45,500 而这一切都可以归结为简单的基础知识,什么是一个数组 611 00:36:45,500 --> 00:36:49,080 这是什么意思,分配和使用内存。 612 00:36:49,080 --> 00:36:51,710 >> 相关的,然后是这样的。 613 00:36:51,710 --> 00:36:54,280 我们只是看了一眼里面的硬盘驱动器。 614 00:36:54,280 --> 00:36:58,440 你还记得一两个星期前,当你将文件拖到回收站或垃圾桶, 615 00:36:58,440 --> 00:37:03,710 发生了什么? >> [学生]没有。 “绝对没有,对不对? 616 00:37:03,710 --> 00:37:05,740 最后,如​​果你运行的磁盘空间不足, 617 00:37:05,740 --> 00:37:08,190 Windows或Mac OS将开始为您删除的文件。 618 00:37:08,190 --> 00:37:10,390 但是,如果你拖动的东西在那里,这不是在所有的安全。 619 00:37:10,390 --> 00:37:13,800 你的室友或朋友或家人做的就是双击,瞧, 620 00:37:13,800 --> 00:37:16,310 所有的粗略的,您尝试删除的文件。 621 00:37:16,310 --> 00:37:19,590 我们大多数人至少知道,你必须右击或控制点击 622 00:37:19,590 --> 00:37:22,310 清空垃圾桶或类似的东西。 623 00:37:22,310 --> 00:37:25,000 但是,即使这样,它不太做的伎俩 624 00:37:25,000 --> 00:37:28,010 因为当你有你的硬盘驱动器上的文件 625 00:37:28,010 --> 00:37:32,770 一些Word文件或某些JPEG,这代表您的硬盘驱动器, 626 00:37:32,770 --> 00:37:35,350 让我们说这个条子在这里表示该文件, 627 00:37:35,350 --> 00:37:38,390 它是由一大堆的0和1。 628 00:37:38,390 --> 00:37:42,470 会发生什么事时,你不仅该文件拖动到垃圾桶或回收站 629 00:37:42,470 --> 00:37:48,020 但也空吗?排序无关。 630 00:37:48,020 --> 00:37:49,640 这不是绝对没有。 631 00:37:49,640 --> 00:37:54,290 现在是不是真的发生在此表的形式,因为少了一些。 632 00:37:54,290 --> 00:37:58,370 因此,有一些种类的数据库或表内的一台计算机的内存 633 00:37:58,370 --> 00:38:03,850 在本质上具有文件的名称,一列一列文件的位置, 634 00:38:03,850 --> 00:38:07,720 这可能是123,只是一个随机位置。 635 00:38:07,720 --> 00:38:14,560 因此,我们可能有一些如x.jpeg和地点123。 636 00:38:14,560 --> 00:38:18,800 然后会发生什么当你真正清空你的回收站? 637 00:38:18,800 --> 00:38:20,330 这消失。 638 00:38:20,330 --> 00:38:23,610 但不会消失的是0和1。 639 00:38:23,610 --> 00:38:26,270 >> 那么,有什么然后连接到pset4的吗? 640 00:38:26,270 --> 00:38:31,240 好了,与pset4,只是因为我们不小心删掉了紧凑型闪存卡 641 00:38:31,240 --> 00:38:35,750 所有这些照片,或只是因为它的坏运气成为损坏 642 00:38:35,750 --> 00:38:38,000 并不意味着“0”和“1”是不是仍然存在。 643 00:38:38,000 --> 00:38:40,410 也许他们几个人都失去了,因为有东西损坏 644 00:38:40,410 --> 00:38:43,320 在这个意义上,一些“0”变成1秒和1秒变成0。 645 00:38:43,320 --> 00:38:47,240 不好的事情都可能发生,因为软件bug或有缺陷的硬件。 646 00:38:47,240 --> 00:38:50,370 但许多这些位,也许他们甚至100%,是仍然存在。 647 00:38:50,370 --> 00:38:55,050 这只是电脑或相机,不知道去哪里JPEG1开始 648 00:38:55,050 --> 00:38:56,910 和JPEG2开始。 649 00:38:56,910 --> 00:39:01,070 但是,如果你作为程序员,知道这些JPEG文件是位精明的 650 00:39:01,070 --> 00:39:06,010 它们看起来像什么,这样你就可以分析“0”和“1和JPEG,JPEG, 651 00:39:06,010 --> 00:39:09,440 你可以写一个程序,基本上只是一个while循环 652 00:39:09,440 --> 00:39:12,820 ,恢复这些文件的每个人。 653 00:39:12,820 --> 00:39:16,030 因此,教训是安全地删除您的文件 654 00:39:16,030 --> 00:39:18,340 如果你想完全避免这种情况。是。 655 00:39:18,340 --> 00:39:21,010 >> [学生]为什么说在您的计算机上 656 00:39:21,010 --> 00:39:23,550 你有更多的内存比你以前吗? 657 00:39:23,550 --> 00:39:27,820 比你以前有更多的内存 - >> [学生]更多的可用内存。 658 00:39:27,820 --> 00:39:29,630 哦。这个问题问得好。 659 00:39:29,630 --> 00:39:32,360 那么为什么你的计算机后清空垃圾桶告诉你 660 00:39:32,360 --> 00:39:34,910 你有更多的自由空间比你以前吗? 661 00:39:34,910 --> 00:39:36,770 简单地说,因为它是在撒谎。 662 00:39:36,770 --> 00:39:40,740 技术上,你有更多的空间,因为现在你所说的 663 00:39:40,740 --> 00:39:43,680 该文件一旦你可以把其他的东西。 664 00:39:43,680 --> 00:39:45,450 但是,这并不意味着这些位去, 665 00:39:45,450 --> 00:39:48,590 和,这并不意味着正在被改变的比特都为0,例如, 666 00:39:48,590 --> 00:39:50,150 为保护您的利益。 667 00:39:50,150 --> 00:39:54,640 相反,如果你安全地删除文件或物理损坏设备, 668 00:39:54,640 --> 00:39:57,300 这确实是有时解决这一问题的唯一途径。 669 00:39:57,300 --> 00:40:02,020 >> 那么,为什么我们不离开上,半吓人的,我们将看到你在周一。 670 00:40:02,020 --> 00:40:07,000 [掌声] 671 00:40:07,780 --> 00:40:10,000 >> [CS50.TV]