1 00:00:00,000 --> 00:00:02,310 [Powered by Google Translate] [第4周,续] 2 00:00:02,310 --> 00:00:04,240 [戴维·J·马兰 - 哈佛大学] 3 00:00:04,240 --> 00:00:07,290 [这是CS50。 - CS50.TV] 4 00:00:07,290 --> 00:00:11,290 >> 这是CS50,这是结束4周。 5 00:00:11,290 --> 00:00:14,030 因此,一些好消息和一些坏消息。 6 00:00:14,030 --> 00:00:26,240 星期一不上课,没有问题设置下周,。 [学生欢呼] 7 00:00:26,240 --> 00:00:28,680 你不会喜欢,这是怎么回事。 8 00:00:28,680 --> 00:00:31,590 但是,我们确实有这个,而不是下周三, 9 00:00:31,590 --> 00:00:37,740 也按照教学大纲周五演讲下周五,这样我们就可以留在赛道上。 10 00:00:37,740 --> 00:00:40,580 但是,一切都将被拍摄下来,像往常一样,所以不用担心。 11 00:00:40,580 --> 00:00:44,100 >> 而对于测验0朝周的结束,我们会做什么 12 00:00:44,100 --> 00:00:47,140 发布课程的网页cs50.net解释 13 00:00:47,140 --> 00:00:50,160 你应该有什么样的期望时,它的第一次测验。 14 00:00:50,160 --> 00:00:55,100 在一般情况下,这将是多项选择题,是非,简答题,短的编码问题。 15 00:00:55,100 --> 00:00:57,360 你不会被预计实现相当于 16 00:00:57,360 --> 00:01:00,030 的问题上,你会看到一个pset中,你有一台电脑 17 00:01:00,030 --> 00:01:03,240 和调试器之类的,但会有小的编码问题。 18 00:01:03,240 --> 00:01:06,900 >> 事实上,得到了CS50测验感的最佳指南是像 19 00:01:06,900 --> 00:01:09,180 就是到cs50.net去,去测验链接, 20 00:01:09,180 --> 00:01:11,920 你可以看到价值在过去几年的测验。 21 00:01:11,920 --> 00:01:16,600 只是实现课程并不总是相同多年来。 22 00:01:16,600 --> 00:01:18,510 有时候,我们增加,有时相减, 23 00:01:18,510 --> 00:01:20,670 所以如果你看到一些话题之一,那些老测验 24 00:01:20,670 --> 00:01:25,380 你不知道它在说什么,这是,我们没有覆盖 25 00:01:25,380 --> 00:01:27,210 或者,我们并没有覆盖它。 26 00:01:27,210 --> 00:01:31,110 但是,评论的形式,这个星期天,星期一和星期二 27 00:01:31,110 --> 00:01:34,770 以及在周日晚上的课程广泛的审查会议 - 28 00:01:34,770 --> 00:01:37,500 课程的网页上公布的时间和地点 - 29 00:01:37,500 --> 00:01:40,120 你有机会检讨课程的教学研究员 30 00:01:40,120 --> 00:01:44,830 今年,无论是在材料部分,作为一个完整的类, 31 00:01:44,830 --> 00:01:48,400 和那些将被拍摄下来,像往常一样。 32 00:01:48,400 --> 00:01:53,380 >> 好的。因此,事不宜迟,评论通过/失败,并添加/删除。 33 00:01:53,380 --> 00:01:57,980 您可能已经看到我的笔记昨晚,这真的只是一些额外的放心 34 00:01:57,980 --> 00:02:01,250 如果你是在那些特别不舒服的,或介于两者之间 35 00:02:01,250 --> 00:02:04,870 和你的感觉只是一点点在你的头上, 36 00:02:04,870 --> 00:02:08,430 实现这确实是很正常的,并有充足的支撑结构, 37 00:02:08,430 --> 00:02:13,530 其中之一办公时间为每提高我的电子邮件昨晚的意图, 38 00:02:13,530 --> 00:02:16,520 实现过类似的选项通过/失败的一类这样的 39 00:02:16,520 --> 00:02:21,540 真的是作为一种机制,采取边关闭的这样一个过程, 40 00:02:21,540 --> 00:02:24,200 因此,再次,如果你花这10个,15个,20个小时 41 00:02:24,200 --> 00:02:28,160 只是想获得一些pset的工作,你知道你的方式有90%-95% 42 00:02:28,160 --> 00:02:32,100 但你不能找到一些该死错误,在一通/失败的排序模型,没关系。 43 00:02:32,100 --> 00:02:36,230 >> 我们的想法是,该机制可以去专注于其他pset 44 00:02:36,230 --> 00:02:39,530 或睡眠,不管它是什么,你要专注于。 45 00:02:39,530 --> 00:02:43,390 所以知道你有,直到下星期二 - 技术上,5日(星期一), 46 00:02:43,390 --> 00:02:50,840 但它是一个节日,所以这下星期二 - 切换合格/不合格分级或反之亦然。 47 00:02:50,840 --> 00:02:54,450 而且,如果你真的在绝壁上,并考虑丢弃完全, 48 00:02:54,450 --> 00:02:56,440 请抓住我讲课后,我。 49 00:02:56,440 --> 00:02:59,990 我们很乐意向你告别之前,至少聊天。 50 00:02:59,990 --> 00:03:03,470 好的。因此,我们开始考虑关闭最后一次训练车轮。 51 00:03:03,470 --> 00:03:06,030 特别是,我们专注于字符串。 52 00:03:06,030 --> 00:03:09,740 String是宣布的CS50库中的东西的, 53 00:03:09,740 --> 00:03:14,340 特别是在该称为cs50.h的文件,我们将在本周和下周开始寻找。 54 00:03:14,340 --> 00:03:17,250 但是,字符串是真的只是一个简化的东西 55 00:03:17,250 --> 00:03:20,980 这是一个有点更arcanely为char *。 56 00:03:20,980 --> 00:03:24,090 CHAR我们熟悉的。这只是一个单一的字符。 57 00:03:24,090 --> 00:03:28,010 *截至周一表示什么? >> [学生]的指针。 58 00:03:28,010 --> 00:03:31,290 一个指针。什么是指针吗? >> [学生]的地址。 59 00:03:31,290 --> 00:03:33,420 >> 这就像一个地址,一个在内存中的位置。 60 00:03:33,420 --> 00:03:35,910 什么是地址或位置,或记忆体? 61 00:03:35,910 --> 00:03:40,290 同样,我们所有的人都有笔记本电脑的演出或2 GB的RAM,最有可能的,这些天, 62 00:03:40,290 --> 00:03:44,160 这意味着你有一个亿或2亿字节值得的内存。 63 00:03:44,160 --> 00:03:46,240 它并不真正的问题是什么身体看起来像, 64 00:03:46,240 --> 00:03:51,220 但要信你可以列出所有的单个字节,自己的笔记本电脑 - 65 00:03:51,220 --> 00:03:54,580 这是0字节,这是第1个字节,这是第2个字节亿 - 66 00:03:54,580 --> 00:03:56,100 而这正是一台电脑做什么。 67 00:03:56,100 --> 00:04:00,030 例如,当您分配的单个字符的空间, 68 00:04:00,030 --> 00:04:02,480 在您的计算机的内存中显然有地方住, 69 00:04:02,480 --> 00:04:05,860 也许是在字节数12345, 70 00:04:05,860 --> 00:04:08,470 这就是这里的某个地方在您的计算机的内存中。 71 00:04:08,470 --> 00:04:12,630 该字符的地址,然后是12345。 72 00:04:12,630 --> 00:04:16,140 >> 现在,在0周,通过现在到目前为止,我们还没有真正关心 73 00:04:16,140 --> 00:04:19,170 在那里存储在内存中的东西,因为我们通常使用的符号, 74 00:04:19,170 --> 00:04:22,540 变量和数组其实在我们的数据。 75 00:04:22,540 --> 00:04:24,950 但是,星期一,今天,你将有 76 00:04:24,950 --> 00:04:27,710 更表达能力编写程序 77 00:04:27,710 --> 00:04:31,330 要真正操纵一台计算机的内存,您认为合适的, 78 00:04:31,330 --> 00:04:33,720 既有良好的目的和坏的, 79 00:04:33,720 --> 00:04:39,620 错误在学习这东西在这一点上是一种很常见的结果。 80 00:04:39,620 --> 00:04:42,460 但什么是它真正的意思,是一个char *? 81 00:04:42,460 --> 00:04:46,140 让继续回到 - 和所承诺的今天,我们会回来Binky。 82 00:04:46,140 --> 00:04:48,670 让我们到这里一个简单的例子。 83 00:04:48,670 --> 00:04:53,060 让我保存这个文件为compare.c,让我在这里得到一些模板代码 84 00:04:53,060 --> 00:05:00,490 所以包括stdio.h中,让我也给自己包括cs50.h.我会在有放大。 85 00:05:00,490 --> 00:05:05,850 让我开始写主要的诠释,主要(无效),现在我想要做这样的事情: 86 00:05:05,850 --> 00:05:13,520 printf(“请给我一个字符串:”),然后我会使用字符串s中得到的getString 87 00:05:13,520 --> 00:05:16,750 从用户得到一个字符串,那么我要问另一个用户。 88 00:05:16,750 --> 00:05:21,870 (“给我另一个字符串:”)和我通过GetString来,我要问他们。 89 00:05:21,870 --> 00:05:27,020 我会打电话给它吨,因为T后,S和S为一个字符串,如果是一个好听的名字,这是非常普通的。 90 00:05:27,020 --> 00:05:30,030 GetString的,现在我只想要做完整性检查,我要去说 91 00:05:30,030 --> 00:05:39,770 (== T),然后我只是要告诉用户输出(“你输入同样的事情!\ n”); 92 00:05:39,770 --> 00:05:45,520 否则,我要打印出来的东西(如“您所键入的不同的东西!\ n”) 93 00:05:45,520 --> 00:05:48,460 或其他的句子。因此,类似的东西。 94 00:05:48,460 --> 00:05:52,200 然后,像往常一样,我会回来0这标志着没有什么糟糕的事情发生, 95 00:05:52,200 --> 00:05:54,400 我要继续前进,编译并运行这个程序。 96 00:05:54,400 --> 00:05:56,540 >> 但在周一,我们运行这个程序, 97 00:05:56,540 --> 00:06:00,420 实际上是说,HELLO你好和再见不再见。 98 00:06:00,420 --> 00:06:03,140 的行为,我们看到的是一个有点像。 99 00:06:03,140 --> 00:06:11,450 让我进入我的源目录,在这里变焦,并让我们做作出比较。 100 00:06:11,450 --> 00:06:14,570 编译没问题。让我跑了比较。给我一个字符串:HELLO。 101 00:06:14,570 --> 00:06:16,300 给我另一个字符串:HELLO。 102 00:06:16,300 --> 00:06:18,000 您输入不同的东西! 103 00:06:18,000 --> 00:06:22,650 好了,让我试试简单的像50,50。您输入不同的东西! 104 00:06:22,650 --> 00:06:25,740 嗨,嗨。所以很明显,这是怎么回事。 105 00:06:25,740 --> 00:06:28,440 但究竟是什么理由来解释为什么? 106 00:06:28,440 --> 00:06:33,850 显然,12号线是完全不正常的。 107 00:06:34,300 --> 00:06:39,430 这里的根本问题是什么?是啊。 >> [学生]的地址进行比较。 108 00:06:39,430 --> 00:06:41,850 是的,没错。它实际上是比较地址 109 00:06:41,850 --> 00:06:44,580 HELLO和HELLO存储。 110 00:06:44,580 --> 00:06:48,290 这不是比较的字母HELLO一遍又一遍, 111 00:06:48,290 --> 00:06:52,370 因为什么是真正发生的事情,这段时间我们一直在使用GetString - 112 00:06:52,370 --> 00:06:56,130 黑板又是我们电脑的内存, 113 00:06:56,130 --> 00:07:00,100 让我们说我调用GetString后声明一个变量s。 114 00:07:00,100 --> 00:07:01,930 我的记忆是什么样子呢? 115 00:07:01,930 --> 00:07:07,070 让我们武断地说,,长相像这样。这是一个正方形。 116 00:07:07,070 --> 00:07:09,040 和几乎所有的时间在屏幕上,我画的一块内存 117 00:07:09,040 --> 00:07:12,860 如果是32位我已经画广场这样的,因为确实在家电, 118 00:07:12,860 --> 00:07:17,380 一个指针,一个地址,为32位。这是一个int一样。 119 00:07:17,380 --> 00:07:19,420 这可以根据计算机系统的不同而有所差异。 120 00:07:19,420 --> 00:07:24,630 你们谁是与你的Mac或PC是64位的事实​​,依稀熟悉, 121 00:07:24,630 --> 00:07:28,120 实际上代表您的电脑使用的是64位指针, 122 00:07:28,120 --> 00:07:33,730 64位地址,并跻身有利的一面,那是你的电脑 123 00:07:33,730 --> 00:07:35,560 可以有更多的RAM比昔日。 124 00:07:35,560 --> 00:07:39,240 长话短说,早在一天当计算机只使用32位 125 00:07:39,240 --> 00:07:42,740 表示地址的最大字节数,你可以代表 126 00:07:42,740 --> 00:07:46,280 在这种情况下,如果你有32位吗? 127 00:07:46,280 --> 00:07:49,590 所以4亿美元,正确的,因为2到32是4亿美元。 128 00:07:49,590 --> 00:07:51,370 这个数字已再次发生的过程。 129 00:07:51,370 --> 00:07:55,240 >> 所以,如果你只有32位,你可以数到的最高数量是大约4亿美元。 130 00:07:55,240 --> 00:07:58,750 但是,这是一个基本的限制,直到几年前的电脑 131 00:07:58,750 --> 00:08:01,180 因为如果你只能算作高为4亿美元, 132 00:08:01,180 --> 00:08:05,270 不要紧,如果你买了8 GB的RAM,甚至5千兆字节的RAM; 133 00:08:05,270 --> 00:08:07,780 你不能指望那么高,所以它是无用的。 134 00:08:07,780 --> 00:08:11,430 您只能访问您的计算机的内存中的第3或4 GB的。 135 00:08:11,430 --> 00:08:14,410 这不再是一个问题了,你可以买的MacBook Pros笔记本电脑和戴尔 136 00:08:14,410 --> 00:08:17,680 8 GB的RAM,甚至更多,这些天。 137 00:08:17,680 --> 00:08:24,100 但是,如果我分配在这个程序很简单指针,指针, 138 00:08:24,100 --> 00:08:28,370 它可能看起来像在屏幕上,因为我们确实需要剥开这层。 139 00:08:28,370 --> 00:08:33,520 我一直在说的字符串,但截至周一,字符串是真正的char *, 140 00:08:33,520 --> 00:08:35,590 一些字符的地址。 141 00:08:35,590 --> 00:08:39,280 因此,让我们的训练轮中断,即使现在我们将继续使用GetString。 142 00:08:39,280 --> 00:08:42,600 所以,我宣布,这是一个内存块,32位。 143 00:08:42,600 --> 00:08:47,370 在这里,默认情况下,在内存中吗? >> [听不见的学生反应] 144 00:08:47,370 --> 00:08:50,040 那是什么? >> [学生]垃圾。 >>垃圾。没错。 145 00:08:50,040 --> 00:08:54,610 如果你的程序员不把一个变量的值,谁知道它是什么呢? 146 00:08:54,610 --> 00:08:57,990 有时你会得到幸运的,它是0,这是怎么样的一个不错的,干净的默认值, 147 00:08:57,990 --> 00:09:00,310 但正如我们所看到周一,有时完全是一派胡言, 148 00:09:00,310 --> 00:09:04,130 一些非常大的正数或负数,从哪儿来? 149 00:09:05,350 --> 00:09:07,010 是啊。 >> [学生]的功能。 >>呀。 150 00:09:07,010 --> 00:09:10,170 >> 通常情况下,被调用的函数,因为以前记得, 151 00:09:10,170 --> 00:09:13,920 当你调用函数在内存中,他们采取了越来越多的空间从下往上, 152 00:09:13,920 --> 00:09:17,040 尽快函数返回时,那段记忆得到重用 153 00:09:17,040 --> 00:09:20,890 ,被称为未来的家伙,谁在使用相同的内存片。 154 00:09:20,890 --> 00:09:23,450 如果你已经离开垃圾在那里,以前的值, 155 00:09:23,450 --> 00:09:28,190 我们可能会误以为S作为有一定的价值时,我们真的不把任何东西存在。 156 00:09:28,190 --> 00:09:30,960 因此,我们在这一点上看起来是这样的RAM。 157 00:09:30,960 --> 00:09:36,030 现在的右手边的第7行,我们调用GetString时, 158 00:09:36,030 --> 00:09:40,150 我们现在做了几个星期,但真的这样做是GetString的吗? 159 00:09:40,150 --> 00:09:43,350 GetString的是一个有点聪明的的CS50人员的书面 160 00:09:43,350 --> 00:09:46,500 ,只要用户开始输入密钥,点击输入, 161 00:09:46,500 --> 00:09:50,010 GetString的数字用户按下了多少按键, 162 00:09:50,010 --> 00:09:53,360 我需要多少个字符分配RAM。 163 00:09:53,360 --> 00:09:55,660 ,RAM,谁知道? 164 00:09:55,660 --> 00:09:58,930 这是在您的计算机上的2千兆字节的内存或诸如此类的东西的地方。 165 00:09:58,930 --> 00:10:05,200 但是,让我们假设计算机空间的单词HELLO。 166 00:10:05,200 --> 00:10:08,710 我输入的字是H-E-L-L-O。 167 00:10:08,710 --> 00:10:13,510 如果我们得出这样的字符序列,我们可以绘制它是这样的。 168 00:10:13,510 --> 00:10:17,860 不过,我需要做额外的事情。结束时的任何字符串在C属于什么? 169 00:10:17,860 --> 00:10:20,710 空字符,这是我们写的\ 0。 170 00:10:20,710 --> 00:10:23,980 这是技术上的数字0,,但反斜线使更清晰 171 00:10:23,980 --> 00:10:28,150 这是字面上的编号为0,整数0; 172 00:10:28,150 --> 00:10:32,440 它不是,例如,报价引文结束,你可能会在键盘上键入0。 173 00:10:32,440 --> 00:10:33,940 因此,这是HELLO。 174 00:10:33,940 --> 00:10:36,350 >> 了什么,我们在周一,类似的函数的GetString 175 00:10:36,350 --> 00:10:39,580 实际上返回所有这几个星期呢? 176 00:10:39,580 --> 00:10:43,960 这不是返回一个字符串,因为这本身并没有真正的意思 177 00:10:43,960 --> 00:10:47,710 因为字符串不存在。他们的一个制造的CS50库的排序。 178 00:10:47,710 --> 00:10:51,300 什么是真正的字符串,技术上呢? >> [学生]这是第一个字符。 179 00:10:51,300 --> 00:10:55,950 没错。这是很简单的第一个字符的地址,用户输入的字词。 180 00:10:55,950 --> 00:11:02,810 所以,如果我的话HELLO结束的时候,人们的字节数123,然后在字节数124, 181 00:11:02,810 --> 00:11:08,320 125,126,等等,如果我只是我从0字节数就到了, 182 00:11:08,320 --> 00:11:12,650 真正的GetString返回简直是数字123。 183 00:11:12,650 --> 00:11:19,270 那么,什么被在s号为123,而不是字母H,而不是这个词HELLO, 184 00:11:19,270 --> 00:11:23,130 很简单的地址,我能找到的第一个字母HELLO。 185 00:11:23,130 --> 00:11:26,500 但是,这似乎并不像足了。我问你一个字符串,而不是一个字符。 186 00:11:26,500 --> 00:11:32,970 那么,如何才能或计算机知道ELLO种以及H? 187 00:11:35,760 --> 00:11:37,460 我们有什么样的协议?是啊。 188 00:11:37,460 --> 00:11:40,100 [学生]不断告诉自己找到一些更多的字符。 “没错。 189 00:11:40,100 --> 00:11:44,570 >> 这种人机惯例,即当你处理字符串, 190 00:11:44,570 --> 00:11:49,410 否则现在已知为char明星,你只需要找出 191 00:11:49,410 --> 00:11:54,350 在生活中的每一个字符串的结束是真的只是一个for循环迭代, 192 00:11:54,350 --> 00:11:57,820 一个while循环,什么的,所以,当你找到的字符串的结尾 193 00:11:57,820 --> 00:12:02,160 哦,现在你可以推断出,整个单词HELLO。 194 00:12:02,160 --> 00:12:04,820 这些与以前的编程经验,你可能知道在Java中 195 00:12:04,820 --> 00:12:09,880 你可以调用。长和在其他语言中,你可以调用长度或类似的。 196 00:12:09,880 --> 00:12:14,060 这是因为,在很多​​语言中,特别是被称为面向对象的语言, 197 00:12:14,060 --> 00:12:18,580 长的东西是种的一块封装在数据本身, 198 00:12:18,580 --> 00:12:24,000 就像我们封装的ID和姓名,房屋内的学生周一。 199 00:12:24,000 --> 00:12:28,700 但是,C是低得多的水平。有没有对象或类的,如果你听说过这些术语。 200 00:12:28,700 --> 00:12:31,490 你真的是内存地址。 201 00:12:31,490 --> 00:12:35,540 因此,这是一种老式的方法较有趣的数据结构。 202 00:12:35,540 --> 00:12:38,760 你有一个开始的第一个字符的地址值,如 203 00:12:38,760 --> 00:12:42,340 ,然后就一些任意的约定,每个人都同意遵守。 204 00:12:42,340 --> 00:12:46,420 因此,如何实现字符串的长度,我们提出了吗? 205 00:12:46,420 --> 00:12:51,360 STRLEN,STRLEN,你们中的一些现在已经用了几次。这是很简单的,对不对? 206 00:12:51,360 --> 00:12:53,060 这就像两行代码。 207 00:12:53,060 --> 00:12:56,140 这几乎是一个某种形式的for循环,也许有一个额外的局部变量。 208 00:12:56,140 --> 00:13:00,540 但strlen的只是一个指针,然后开始寻找\ 0。 209 00:13:00,540 --> 00:13:05,190 >> 而一旦它发现它,它可以返回总数的步骤,它采取了在该字符串中。 210 00:13:05,190 --> 00:13:07,150 因此,我们可以推断,这是下一个。 211 00:13:07,150 --> 00:13:11,850 假设,然后在第10行,因为我已经做了,我宣布吨。 212 00:13:11,850 --> 00:13:14,280 这是一些垃圾的价值。在第一谁知道? 213 00:13:14,280 --> 00:13:18,490 但在我右手边的10调用的getString再次。 214 00:13:18,490 --> 00:13:20,050 谁知道在哪里结束呢? 215 00:13:20,050 --> 00:13:23,830 让我们武断地说,操作系统搜房的方式在这里。 216 00:13:23,830 --> 00:13:28,610 我正好不约而同地再次键入H-E-L-L-O, 217 00:13:28,610 --> 00:13:31,260 因此,我们可以得出相同类型的图像。 218 00:13:31,260 --> 00:13:34,290 但事实上,我已经重新绘制这幅画是故意的 219 00:13:34,290 --> 00:13:37,720 因为这是一个不同的HELLO超过这一点。 220 00:13:37,720 --> 00:13:43,920 因此,这里,这可能会对位置456,这是457,等等。 221 00:13:43,920 --> 00:13:47,170 那么,什么被放在其中的问号? 222 00:13:47,170 --> 00:13:50,190 在这种情况下,456。 223 00:13:50,190 --> 00:13:53,540 我们选择这些数字随意,因为今天真 224 00:13:53,540 --> 00:13:57,110 我们不会那么在乎任何事物的地址是什么。 225 00:13:57,110 --> 00:14:02,690 我们所关心的是,我们可以计算出地址的某些数据,如HELLO。 226 00:14:02,690 --> 00:14:07,100 >> 所以,真的是大多数人都在谈论的内存地址时,计算机科学 227 00:14:07,100 --> 00:14:10,210 和谈论的指针具体而言, 228 00:14:10,210 --> 00:14:14,220 而不是费心找出123 - 谁在乎这个东西实际上是, 229 00:14:14,220 --> 00:14:17,440 我们只知道它是在一些数字地址 - 230 00:14:17,440 --> 00:14:22,180 我们简化了世界,只是说S是指向该字符 231 00:14:22,180 --> 00:14:25,080 ,t为指向这个角色。 232 00:14:25,080 --> 00:14:27,430 而事实上,它是一个箭头是很有意 233 00:14:27,430 --> 00:14:31,610 因为从字面上现在s是指向在H和t指向其他的H 234 00:14:31,610 --> 00:14:34,720 因为在一天结束时,它并没有关系的地址是什么, 235 00:14:34,720 --> 00:14:40,240 但它的问题,我们有一些代码的表达能力,地址。 236 00:14:40,240 --> 00:14:42,730 我们还没有真正操纵这些地址,只是还没有 237 00:14:42,730 --> 00:14:47,770 所以我们会看到,在这里我们可以没错,排序做的事情与指针, 238 00:14:47,770 --> 00:14:52,030 但现在在第12行从字面上我们比较的是什么值 239 00:14:52,030 --> 00:14:55,500 根据这个故事在第12行吗? 240 00:14:56,570 --> 00:15:01,290 我们说的是123,等于等于456?这绝对不是这样的。 241 00:15:01,290 --> 00:15:05,320 甚至在概念上,这个指针肯定是不一样的,因为这 242 00:15:05,320 --> 00:15:09,500 因为你叫GetString的两倍,和GetString不会尝试是超级聪明, 243 00:15:09,500 --> 00:15:12,470 它不会尝试来实现的,哦,你键入HELLO 5分钟前; 244 00:15:12,470 --> 00:15:15,090 让我给你的,因为我以前给你相同的指针, 245 00:15:15,090 --> 00:15:18,450 它只是分配一个新的内存块,每次调用它。 246 00:15:18,450 --> 00:15:20,350 >> 那么,我们如何解决这个问题? 247 00:15:20,350 --> 00:15:24,270 如果需要更高的水平,我想比较字符串HELLO HELLO - 248 00:15:24,270 --> 00:15:28,680 我不关心的指针 - 我该如何去回答这个问题, 249 00:15:28,680 --> 00:15:31,980 用户键入了同样的事情?有什么必要在这里?是啊。 250 00:15:31,980 --> 00:15:35,200 [学生]使用的功能。 >>我可以使用一个函数的开箱即用。 251 00:15:35,200 --> 00:15:38,170 我可以使用一个函数调用strcmp,S-T-R-C-M-P, 252 00:15:38,170 --> 00:15:41,190 只是说字符串比较的缩写形式。 253 00:15:41,190 --> 00:15:45,070 如果我们进入,例如,比较两对,这是在今天的讲义, 254 00:15:45,070 --> 00:15:46,690 我这样做。 255 00:15:46,690 --> 00:15:51,750 我一直下降到26左右,一切从1号线 256 00:15:51,750 --> 00:15:54,360 现在请大家注意,这部分也发生了一点点。 257 00:15:54,360 --> 00:15:57,690 让我们忽略了一会儿,第28行只集中在这一个。 258 00:15:57,690 --> 00:16:00,410 我们说什么(星期一),海峡比较不? 259 00:16:00,410 --> 00:16:05,200 它处理的过程中,在这种情况下,服用2指针,s和t, 260 00:16:05,200 --> 00:16:08,480 排序几乎把手指放在这2个字母, 261 00:16:08,480 --> 00:16:11,530 必须做的是像一个while循环或循环的东西, 262 00:16:11,530 --> 00:16:16,050 ,它说,这是相同的吗?如果是这样,将手指或指针向前移动。 263 00:16:16,050 --> 00:16:17,970 这是相同的,这些相同的,这些是相同的, 264 00:16:17,970 --> 00:16:22,710 这是相同的,这是一样的吗?而且哦,我在结尾的字符串s和t。 265 00:16:22,710 --> 00:16:26,780 我还没有发现任何矛盾。是的,这些字符串是相同的。 266 00:16:26,780 --> 00:16:31,940 什么STR比较的回报,如果两个字符串是相同的,显然是吗?零。 267 00:16:31,940 --> 00:16:35,900 所以0是很好的,因为如果在这种情况下,则返回-1或+1, 268 00:16:35,900 --> 00:16:40,560 这意味着,只是发生之前按字母顺序或在t。 269 00:16:40,560 --> 00:16:43,760 为什么会是有用的,它告诉你有一个函数的字符串之前 270 00:16:43,760 --> 00:16:46,720 后,在一本字典吗? 271 00:16:46,720 --> 00:16:48,740 [学生]搜索。 >>搜索和排序。 272 00:16:48,740 --> 00:16:51,730 >> 所以,你可以做的事情,如的二进制搜索或泡沫排序或归并排序 273 00:16:51,730 --> 00:16:53,230 你要比较的东西。 274 00:16:53,230 --> 00:16:56,420 到目前为止,我们已经削减某些角落,只谈到排序 275 00:16:56,420 --> 00:16:59,430 的背景下的数字,因为它是好的和简单的说说, 276 00:16:59,430 --> 00:17:02,430 但你一定可以比较字符串,苹果,香蕉, 277 00:17:02,430 --> 00:17:05,349 因为如果苹果被称为到来之前,香蕉,同样, 278 00:17:05,349 --> 00:17:09,319 你可以将字符串大约在内存中一样罗布与归并排序的视频 279 00:17:09,319 --> 00:17:15,880 我们在这里所做过的舞台上,选择排序,插入排序,冒泡排序。 280 00:17:15,880 --> 00:17:18,710 所以我们可以采取什么地方?让我们来试试这个。 281 00:17:18,710 --> 00:17:23,980 让我们的忘记了一会儿,这个教训,尝试和复制1.C做到以下几点。 282 00:17:23,980 --> 00:17:26,800 我说在第21行打印的东西, 283 00:17:26,800 --> 00:17:28,520 然后我得到了来自用户的字符串, 284 00:17:28,520 --> 00:17:30,690 然后我检查了。 285 00:17:30,690 --> 00:17:33,620 我们还没有真正得到这个习惯,但现在,让我们做到这一点。 286 00:17:33,620 --> 00:17:40,990 实际,让我们剥开这层。这是真正的char *。这家伙是真正的char *。 287 00:17:40,990 --> 00:17:45,690 所以,这是什么意思进行检查,如果S == NULL? 288 00:17:45,690 --> 00:17:48,380 事实证明,当你调用一个函数一样的GetString 289 00:17:48,380 --> 00:17:51,540 或更一般只要求一台电脑给你一些内存, 290 00:17:51,540 --> 00:17:53,030 东西可以去错了。 291 00:17:53,030 --> 00:17:56,630 你可能是疯了,问TB的内存的电脑 292 00:17:56,630 --> 00:18:01,780 问万亿字节的内存,只是不存在于电脑, 293 00:18:01,780 --> 00:18:05,130 但GetString和其他功能的大喊大叫,你需要通过某种方式 294 00:18:05,130 --> 00:18:06,820 如果你问太多。 295 00:18:06,820 --> 00:18:10,450 的GetString这是,如果你要求更多的内存 296 00:18:10,450 --> 00:18:14,250 比在电脑上,即使这是超级,超级的低概率 297 00:18:14,250 --> 00:18:17,730 因为我们要输入一个万字符,然后按下回车键, 298 00:18:17,730 --> 00:18:21,980 但概率很低,尽管它可能是,但我仍然要检查,以防万一, 299 00:18:21,980 --> 00:18:26,120 GetString时,回答等功能,返回的特殊值, 300 00:18:26,120 --> 00:18:30,630 如果出了问题是NULL全部大写。 301 00:18:30,630 --> 00:18:36,520 >> 什么是空? NULL恰好表示指针。它的内存地址为0。 302 00:18:36,520 --> 00:18:40,800 世界决定意,如果这是我的电脑的内存 - 你知道吗? - 303 00:18:40,800 --> 00:18:46,260 我们要偷的每一台计算机的内存只有1个字节,这是位置0。 304 00:18:46,260 --> 00:18:49,560 我们要去给它一个昵称为NULL,我们要保证 305 00:18:49,560 --> 00:18:52,660 ,我们永远不会真正把真实的数据 306 00:18:52,660 --> 00:18:56,770 因为我们只是任意需要一个特殊的值,又名NULL,0, 307 00:18:56,770 --> 00:19:00,230 因此,我们可以大声喝斥用户,如果出现错误。 308 00:19:00,230 --> 00:19:03,590 否则,你可能不知道0意味着把这里的东西 309 00:19:03,590 --> 00:19:05,490 或它意味着出事了吗? 310 00:19:05,490 --> 00:19:09,190 我们都同意,返回NULL意味着什么, 311 00:19:09,190 --> 00:19:11,700 没有实际地址返回。 312 00:19:11,700 --> 00:19:15,210 现在,在这里我只是通过我的人的惯例,我返回1,从主 313 00:19:15,210 --> 00:19:17,040 如果出现错误。 314 00:19:17,040 --> 00:19:20,650 这是因为主要的回报的约定是返回0,如果好, 315 00:19:20,650 --> 00:19:22,990 或一些其他的值,如果坏。 316 00:19:22,990 --> 00:19:28,200 但是GetString和交易功能,在内存中返回NULL,如果出现坏。 317 00:19:28,200 --> 00:19:33,480 >> 好吧。不幸的是,第27行,超级简单,但它是完全无法复制的字符串。 318 00:19:33,480 --> 00:19:35,740 为什么呢?我们可以看到如下。 319 00:19:35,740 --> 00:19:40,120 我要求在27行s的副本,并呼吁它吨。 320 00:19:40,120 --> 00:19:45,790 所以我不会问用户时间2串;我只是说在s 321 00:19:45,790 --> 00:19:47,870 应在T。 322 00:19:47,870 --> 00:19:52,890 所以,现在只是证明这是多么破碎,第29行起,我在做什么? 323 00:19:52,890 --> 00:19:56,980 首先我检查如果t的长度是大于0的。 324 00:19:56,980 --> 00:19:59,330 有一些字符串。用户输入的东西英寸 325 00:19:59,330 --> 00:20:03,410 第32行,显然是什么? 326 00:20:03,410 --> 00:20:08,910 听不见的学生回应] >>权。您可以推断,从我说的做。 327 00:20:08,910 --> 00:20:13,200 但在技术上,这是什么做的? T [0]代表什么? 328 00:20:13,200 --> 00:20:15,140 [学生]:第零个字符。 >> [马兰]第零个字符。 329 00:20:15,140 --> 00:20:19,620 或者,更人性化的,在T的第一个字符,不管它是什么,H,也许在这种情况下。 330 00:20:19,620 --> 00:20:24,990 和toupper做什么它说。它利用第零个字符的T和它改变它。 331 00:20:24,990 --> 00:20:28,430 因此,这意味着第零个字符的T,大写, 332 00:20:28,430 --> 00:20:30,320 在相同的位置把它放回去。 333 00:20:30,320 --> 00:20:35,540 所以,如果我键入Hello小写字母,这应该改变小写h资本H. 334 00:20:35,540 --> 00:20:41,400 但问题是,在35和36什么,我做的是打印出我们的s和t。 335 00:20:41,400 --> 00:20:43,120 你的直觉是什么? 336 00:20:43,120 --> 00:20:47,250 我究竟要什么,如果我输入了全部用小写吗? 337 00:20:47,250 --> 00:20:52,280 这是怎么回事,列印吗? >> [听不见的学生反应]“那是什么? 338 00:20:52,280 --> 00:20:58,360 [学生]:大H,其余小。 >>大H,其余小的,S或T? 339 00:20:58,360 --> 00:21:03,170 [学生]两个。 >>两种。没错。所以,让我们来看看这里发生了什么事情。 340 00:21:03,170 --> 00:21:08,380 >> 让我去和编译。这是COPY1,所以COPY1。好的。 341 00:21:08,380 --> 00:21:14,840 放大,让我继续运行COPY1,输入,想说什么:您好,小写字母。 342 00:21:14,840 --> 00:21:19,570 资本化的副本,但它显然资本化原, 343 00:21:19,570 --> 00:21:22,070 因为现在发生在这个故事吗? 344 00:21:22,070 --> 00:21:27,030 在第27行,其实我不似乎被复制的字符串, 345 00:21:27,030 --> 00:21:30,450 但即使你可能直观地希望的情况下, 346 00:21:30,450 --> 00:21:33,680 如果你仔细想想这张照片,我真正做了什么? 347 00:21:33,680 --> 00:21:35,410 一半的图片是相同的。 348 00:21:35,410 --> 00:21:39,390 因此,让我们回滚的时间,使吨尚不存在的故事。 349 00:21:39,390 --> 00:21:43,160 S可以存在的故事,但让我们小写您好,这时间。 350 00:21:43,160 --> 00:21:46,710 因此,让我解决了我的实际输入数字。 351 00:21:46,710 --> 00:21:51,280 在这种情况下,在这里,我们有H-E-L-L-O。 352 00:21:51,280 --> 00:21:58,050 我们将以此作为一个字符序列,在这里把我的分割线,我的\ 0。 353 00:21:58,050 --> 00:22:05,980 因此,这是我们在哪里,只要1号线24上下的,给予或采取,已执行。 354 00:22:05,980 --> 00:22:07,800 这是我记忆中的画面。 355 00:22:07,800 --> 00:22:10,800 当我到第27行,会发生什么呢? 356 00:22:10,800 --> 00:22:14,730 就像以前一样,我得到一个指针,我会画这个广场。 357 00:22:14,730 --> 00:22:19,740 这就是所谓的T。默认情况下,它的价值?谁知道?一些垃圾的价值。 358 00:22:19,740 --> 00:22:22,060 >> 因此,我将抽象为一个问号。 359 00:22:22,060 --> 00:22:27,670 尽快右手边的第27行执行,我把里面的T? 360 00:22:27,670 --> 00:22:30,770 同样的事情,在s。 361 00:22:30,770 --> 00:22:34,120 因此,如果我们的时刻删除这个抽象的箭头和我们说, 362 00:22:34,120 --> 00:22:40,330 哦,这是内存加载地址123,当你说T得到s,分号, 363 00:22:40,330 --> 00:22:42,700 你从字面上把123在这里。 364 00:22:42,700 --> 00:22:45,200 现在,如果我们种简化我们的世界再次与图片, 365 00:22:45,200 --> 00:22:48,750 你真的做的只是另一个箭头可以使你的世界 366 00:22:48,750 --> 00:22:52,910 从t到指向完全相同的字符串。 367 00:22:52,910 --> 00:22:59,730 所以,当我在31和32号线去改变T [0], 368 00:22:59,730 --> 00:23:05,580 什么是T [0]显然与现在的代名词吗? [0] 369 00:23:05,580 --> 00:23:07,030 所以这一切的发生。 370 00:23:07,030 --> 00:23:09,900 即使这种感觉有点低的水平,神秘的 371 00:23:09,900 --> 00:23:12,760 这种感觉就像也许是直观的,这应该只是工作 - 372 00:23:12,760 --> 00:23:15,410 我复制的东西,它只是工作 - 373 00:23:15,410 --> 00:23:18,590 如果你真的觉得什么真的是一个字符串,它是一个char *。 374 00:23:18,590 --> 00:23:21,700 嗯,那是什么?这是一些字符的地址。 375 00:23:21,700 --> 00:23:24,930 然后,也许更有意义,当你尝试做一些事情 376 00:23:24,930 --> 00:23:29,220 超级看似简单的这样,你做的是复制一个内存地址。 377 00:23:29,220 --> 00:23:32,530 你的字符串本身实际上没有做任何事情。 378 00:23:32,530 --> 00:23:37,500 所以,即使你不知道你将如何解决这个问题的代码, 379 00:23:37,500 --> 00:23:45,080 高的水平,从理论上讲,是什么,我们需要做的,以使TA s的真实副本,显然吗? 380 00:23:46,670 --> 00:23:48,820 是啊。 >> [学生]给它一个新的位置吗? “没错。 381 00:23:48,820 --> 00:23:50,800 >> 我们需要,给T A品牌新的位置。 382 00:23:50,800 --> 00:23:55,230 我们需要以某种方式创造的世界中,我们得到了一个新的内存块, 383 00:23:55,230 --> 00:24:00,090 这只是为清楚起见,我会画右下面这一个,但它并不需要在那里。 384 00:24:00,090 --> 00:24:04,880 但它需要是相同的大小,所以在同一个地方,我给你画这些垂直线。 385 00:24:04,880 --> 00:24:09,720 这是罚款,如果最初全部是垃圾。谁知道是什么吗? 386 00:24:09,720 --> 00:24:13,850 第1步将有尽可能多的内存给我,因为我需要 387 00:24:13,850 --> 00:24:18,630 适合的副本招呼,然后找出如何复制的H这里,这里的电子, 388 00:24:18,630 --> 00:24:20,390 升这里,等等。 389 00:24:20,390 --> 00:24:24,880 但是,这已经觉得有点明显,即使一些细节仍是抽象的。 390 00:24:24,880 --> 00:24:28,690 这个字符串复制到这一点,它只是一个for循环或while循环 391 00:24:28,690 --> 00:24:31,580 你变得更熟悉的东西。 392 00:24:31,580 --> 00:24:35,970 所以,让我们来试试这个。让我进入copy2.c。 393 00:24:35,970 --> 00:24:43,270 在copy2.c我们具有几乎相同的程序,除了第27行。 394 00:24:43,270 --> 00:24:47,260 它看起来有点复杂,但如果我们把它分解一块一块的, 395 00:24:47,260 --> 00:24:48,950 的左手侧是相同的。 396 00:24:48,950 --> 00:24:52,790 字符* T在内存中创建了这件事情,但一个问号 397 00:24:52,790 --> 00:24:54,680 因为我们不知道什么是有默认。 398 00:24:54,680 --> 00:24:57,920 在右手边,我们现在引入一个新的函数malloc的, 399 00:24:57,920 --> 00:25:00,640 内存分配的,给我的记忆, 400 00:25:00,640 --> 00:25:06,900 它显然需要多少个参数,括号里面的东西有多少? 401 00:25:09,660 --> 00:25:12,130 我听到怨言,1和2,但它仅仅是1。 402 00:25:12,130 --> 00:25:15,320 有没有逗号,这意味着仅有1括号内的事情。 403 00:25:15,320 --> 00:25:17,720 即使有其他括号,我要强调 404 00:25:17,720 --> 00:25:21,460 最外层的括号里面是什么,它​​是这个表达式: 405 00:25:21,460 --> 00:25:25,880 (strlen的()+ 1)* sizeof(char)的的。 406 00:25:25,880 --> 00:25:29,190 因此,如果我们真的该好好想一想,这是说给我s的长度。 407 00:25:29,190 --> 00:25:34,440 我为什么,虽然,加1到的长度? >> [听不见的学生反应] 408 00:25:34,440 --> 00:25:40,200 没错。我们需要空间,这家伙的尾巴,有没有英文的意思第六个字符 409 00:25:40,200 --> 00:25:42,250 但确实有特殊的纲领性意义。 410 00:25:42,250 --> 00:25:46,800 >> 所以我们需要一个+ 1,因为人意料的strlen返回的长度, 411 00:25:46,800 --> 00:25:50,890 打招呼或5,它不给你额外的空字符。 412 00:25:50,890 --> 00:25:52,980 所以,我手动添加+ 1。 413 00:25:52,980 --> 00:25:56,060 然后这个,*大小(字符),我们还没有看到这样的情况。 414 00:25:56,060 --> 00:25:57,480 这不是技术上的功能。 415 00:25:57,480 --> 00:26:04,150 这是一个特殊的关键字,它只是告诉你的计算机上的某些数据类型的大小是 416 00:26:04,150 --> 00:26:06,980 因为在现实中,我们中的一些人有32位计算机。 417 00:26:06,980 --> 00:26:10,900 我有一个很老的电脑在家里,它仅使用32位来表示指针。 418 00:26:10,900 --> 00:26:13,900 所以,如果我做的数据类型的大小,它可能是32位。 419 00:26:13,900 --> 00:26:18,300 但是,如果我用我的新奇特的电脑,我可能会得到64位值 420 00:26:18,300 --> 00:26:20,510 类似地址。 421 00:26:20,510 --> 00:26:25,400 因此,在这种情况下,仅仅是超级安全,我们不打算到硬编码类似的东西 - 422 00:26:25,400 --> 00:26:28,740 那么,究竟是根据什么说了这么远的一个字符的大小吗? 423 00:26:28,740 --> 00:26:34,450 我们已经差不多口头上说是1个字节,这几乎是全线。 424 00:26:34,450 --> 00:26:37,000 但同样,假设往往是坏的。 425 00:26:37,000 --> 00:26:40,850 他们导致bug的软件,如果人们使用软件的方式,你不打算。 426 00:26:40,850 --> 00:26:44,750 因此,让我们的抽象之遥,只是更一般的说 427 00:26:44,750 --> 00:26:46,830 我需要很多的内存块 428 00:26:46,830 --> 00:26:50,210 并且每个块的存储器应该是相当于一个字符的大小, 429 00:26:50,210 --> 00:26:54,870 这是在实际上等于在此情况下为1,但它是一个更通用的方法将其写入。 430 00:26:54,870 --> 00:27:00,460 因此,如果这个词是个招呼,多少字节的malloc显然是分配给你好呢? 431 00:27:00,460 --> 00:27:04,980 [学生]六。 “六。正如很多,因为我们有问号在屏幕上。 432 00:27:04,980 --> 00:27:07,800 然后采取的猜测现在根据你的理解的GetString 433 00:27:07,800 --> 00:27:12,790 可能是什么的malloc返回? >> [学生]的地址。 434 00:27:12,790 --> 00:27:17,020 地址是什么?第一块内存。 435 00:27:17,020 --> 00:27:20,670 >> 我们不知道那里有什么,因为其他一些功能 436 00:27:20,670 --> 00:27:23,010 已使用内存之前。 437 00:27:23,010 --> 00:27:28,380 但malloc的,喜欢的GetString,返回地址的第一个字节的内存 438 00:27:28,380 --> 00:27:30,540 它已经为你留。 439 00:27:30,540 --> 00:27:38,380 然而,它不会做一个反斜杠空字符填补这个空白 440 00:27:38,380 --> 00:27:43,030 因为事实证明,你可以使用malloc分配的任何整数,字符串,数组, 441 00:27:43,030 --> 00:27:45,700 花车,学生结构。 442 00:27:45,700 --> 00:27:47,750 您可以使用malloc完全通用。 443 00:27:47,750 --> 00:27:51,470 它不关心或者知道你分配内存。 444 00:27:51,470 --> 00:27:55,810 因此,这将是放肆的malloc把\ 0 445 00:27:55,810 --> 00:27:58,340 在每一个内存块,它给你 446 00:27:58,340 --> 00:28:02,620 因为\ 0的字符串的事情仅仅是一个惯例。 447 00:28:02,620 --> 00:28:06,310 它不使用int类型,它不使用的花车,它不是供学生使用。 448 00:28:06,310 --> 00:28:11,730 这样一来,用malloc是疑难杂症的负担是完全在你的程序员 449 00:28:11,730 --> 00:28:16,790 记得多少字节分配,而不是以往任何时候都使用一个for循环 450 00:28:16,790 --> 00:28:21,570 或while循环的边界的内存块,你已经走过去。 451 00:28:21,570 --> 00:28:23,540 换句话说,只要你分配内存, 452 00:28:23,540 --> 00:28:28,510 你不能要求操作系统,哦,顺便说一下,有多大的内存块是这样的吗? 453 00:28:28,510 --> 00:28:32,080 这完全取决于你要记住,如果你需要的值。 454 00:28:32,080 --> 00:28:34,330 >> 因此,让我们来看看如何我继续使用该内存。 455 00:28:34,330 --> 00:28:38,430 在28和29号线,我为什么这样做呢? 456 00:28:39,850 --> 00:28:42,260 只是总的仔细检查。 457 00:28:42,260 --> 00:28:45,110 以防万一出事了,我问一些疯狂的内存量 458 00:28:45,110 --> 00:28:48,690 或我有这么多的事情在计算机上运行,​​根本就没有足够的内存, 459 00:28:48,690 --> 00:28:51,780 那样的话,我至少要检查是否为NULL。 460 00:28:51,780 --> 00:28:55,260 在现实中,大多数计算机给你的幻觉,每一个程序 461 00:28:55,260 --> 00:28:57,080 可以使用全部的RAM, 462 00:28:57,080 --> 00:29:00,740 但即便如此,如果用户在一些疯狂的长字符串,也许是因为他们是一个坏家伙 463 00:29:00,740 --> 00:29:03,440 他们实际上是想你的程序崩溃或攻入, 464 00:29:03,440 --> 00:29:07,300 你至少要检查返回值的malloc和是否等于null。 465 00:29:07,300 --> 00:29:11,630 如果是这样,就让我们现在退出,因为我不知道该怎么做,在这种情况下,。 466 00:29:11,630 --> 00:29:13,950 如何复制的字符串?有一些方法来做到这一点。 467 00:29:13,950 --> 00:29:18,850 有STR功能在C复制,但它是超级简单的,我们能够做到这一点,老式的方法。 468 00:29:18,850 --> 00:29:23,110 >> 首先,让我弄清楚什么s的长度。 469 00:29:23,110 --> 00:29:26,930 我可以把这个循环中的,但我只是把它在这里为清晰。 470 00:29:26,930 --> 00:29:30,610 所以N存储原始字符串的长度,这显然是5。 471 00:29:30,610 --> 00:29:35,290 然后在我的for循环,我迭代从0到n, 472 00:29:35,290 --> 00:29:40,940 在每次迭代我把[]内为t [I]。 473 00:29:40,940 --> 00:29:45,060 所以,这就是我暗示,我的手指在琴弦前。 474 00:29:45,060 --> 00:29:49,260 由于for循环遍历这个样子,我要被复制h进这里, 475 00:29:49,260 --> 00:29:52,890 E到这儿的时候,到这里,因为这是,这是T。 476 00:29:52,890 --> 00:29:58,770 那么最后,在第35行,为什么我这样做吗? 477 00:29:58,770 --> 00:30:03,770 我需要确保我结束的字符串t。 478 00:30:03,770 --> 00:30:06,170 我这样做,是这样是超级明确的。 479 00:30:06,170 --> 00:30:09,510 但提出,一个人,如果你能这样做,以不同的方式。 480 00:30:09,510 --> 00:30:13,930 我并不真的需要35行。有另一种方式来做到这一点。 481 00:30:13,930 --> 00:30:18,880 是啊。 >> [听不见的学生反应] >>说它响亮。 482 00:30:18,880 --> 00:30:20,960 [学生]小于或等于。 “没错。 483 00:30:20,960 --> 00:30:24,450 我们只能说小于或等于n,它一直不好一般 484 00:30:24,450 --> 00:30:28,190 因为我们几乎总是等于我们要计算的东西 485 00:30:28,190 --> 00:30:30,000 我们去太远。 486 00:30:30,000 --> 00:30:32,170 但请记住,我们多少字节分配? 487 00:30:32,170 --> 00:30:37,210 我们分配的strlen的S,5 + 1共6个。 488 00:30:37,210 --> 00:30:39,980 因此,在这种情况下,我们可以做这样的事情 489 00:30:39,980 --> 00:30:46,450 这样我们就复制不只是打招呼,但在“\ 0”在最后。 490 00:30:46,450 --> 00:30:49,860 另外,我们可以使用一个功能称为STR副本,STRCPY, 491 00:30:49,860 --> 00:30:51,700 但不会是几乎一样多的乐趣。 492 00:30:51,700 --> 00:30:54,000 但是,这是它的引擎盖下方。 493 00:30:54,000 --> 00:30:56,050 最后,我们像以前一样做同样的事情。 494 00:30:56,050 --> 00:31:01,620 我利用T然后我要求原来看起来像这样的副本看起来像。 495 00:31:01,620 --> 00:31:08,570 因此,让我们试试这个。让我在这里。请COPY2。我们会放大在,并运行COPY2。 496 00:31:08,570 --> 00:31:13,840 我要输入小写字母,而事实上我得到小写的原始 497 00:31:13,840 --> 00:31:16,930 但资本你好的副本。 498 00:31:16,930 --> 00:31:20,300 但我没有这样做,只是还没有。我要在这里做最后一件事。 499 00:31:20,300 --> 00:31:28,000 46和47显然是释放内存,但是,实际上是什么意思呢? 500 00:31:28,000 --> 00:31:33,250 我在做什么,你认为,通过调用第46行和第47行吗? 501 00:31:33,250 --> 00:31:38,900 什么样的影响?是啊。 502 00:31:38,900 --> 00:31:43,140 [听不见的学生回应] >>没错。 503 00:31:43,140 --> 00:31:46,380 >> ,你只是告诉操作系统,嘿嘿,这个内存。 504 00:31:46,380 --> 00:31:48,320 现在,您可以用它给别人。 505 00:31:48,320 --> 00:31:50,790 这里是一个很好的例子,垃圾值。 506 00:31:50,790 --> 00:31:55,430 我刚才用这个记忆写下来的单词hello在2个地方, 507 00:31:55,430 --> 00:31:57,490 这里,这里,这里,和这里。 508 00:31:57,490 --> 00:32:00,910 因此,这是H-E-L-L-O-\ 0。 509 00:32:00,910 --> 00:32:06,960 但后来我打电话第​​46行和第47行,你知道会发生什么的图片吗? 510 00:32:06,960 --> 00:32:10,010 其实,等待,这张照片是旧的。 511 00:32:10,010 --> 00:32:12,550 一旦我们的副本,这家伙居然指指点点, 512 00:32:12,550 --> 00:32:16,110 让我们删除的数字,只是抽象掉,因为我们的箭再次。 513 00:32:16,110 --> 00:32:19,370 这幅画中会发生什么,当我打电话免费? 514 00:32:19,370 --> 00:32:22,750 [听不见的学生响应>>甚至没有。 515 00:32:22,750 --> 00:32:29,510 如果我打电话s和t - 样的一个棘手的问题 - 这幅画不改变 516 00:32:29,510 --> 00:32:33,880 因为调用s,并呼吁只是告诉操作系统, 517 00:32:33,880 --> 00:32:39,010 哎,你可以使用此内存,但它并没有改变为null 518 00:32:39,010 --> 00:32:41,840 或一些特殊的字符,它不改变这一点, 519 00:32:41,840 --> 00:32:47,350 它不改变H或E或L或升或o在别的任何地方。 520 00:32:47,350 --> 00:32:51,610 的图片,只要你通话完全免费,没有任何变化。 521 00:32:51,610 --> 00:32:56,570 ,这其中就有原产地的垃圾值,因为如果我再在这个程序 522 00:32:56,570 --> 00:33:01,010 要求更多的内存GetString或malloc或类似的操作系统, 523 00:33:01,010 --> 00:33:04,900 和操作系统的说,当然,我有12个字节的内存刚刚释放, 524 00:33:04,900 --> 00:33:08,080 使用这些方法,你有什么要交吗? 525 00:33:08,080 --> 00:33:10,830 你要交给一个内存块,我们通常会画 526 00:33:10,830 --> 00:33:13,700 带问号的,但这些问号是什么? 527 00:33:13,700 --> 00:33:17,000 他们正好是H-E-L-L-O,H-E-L-L-O。 528 00:33:17,000 --> 00:33:20,940 这是我们的新的垃圾值,只要你释放该内存。 529 00:33:20,940 --> 00:33:22,750 >> 这里也有一个现实世界的含义。 530 00:33:22,750 --> 00:33:24,720 这恰好与RAM,但您的计算机 531 00:33:24,720 --> 00:33:26,720 其实做同样的事情磁盘。 532 00:33:26,720 --> 00:33:30,620 我们再谈谈,特别是与未来的问题集中在取证集。 533 00:33:30,620 --> 00:33:36,170 但到底发生了什么,如果你有一些敏感的财务文件在您的桌面上 534 00:33:36,170 --> 00:33:39,600 或一些粗略的JPEG和将其拖动到您的垃圾, 535 00:33:39,600 --> 00:33:44,390 当你把它拖到垃圾桶或回收站时,会发生什么情况? 536 00:33:44,390 --> 00:33:47,240 你知道我在说什么。 [笑声] 537 00:33:47,240 --> 00:33:52,370 当你的证据拖动到回收站或垃圾桶,会发生什么情况? 538 00:33:52,370 --> 00:33:55,920 [听不见的学生反应] 539 00:33:55,920 --> 00:33:58,000 好了,所以小心。当你这样做,会发生什么情况? 540 00:33:58,000 --> 00:34:01,030 简短的答案是什么,对不对? 541 00:34:01,030 --> 00:34:04,790 粗略的或敏感的文件仍然只是坐在那里,在您的硬盘驱动器上的某个地方。 542 00:34:04,790 --> 00:34:07,940 我们大多数人至少已经了解到硬盘的方式,你需要清空你的回收站 543 00:34:07,940 --> 00:34:10,429 或回收站删除的文件。 544 00:34:10,429 --> 00:34:13,440 事实上,当你右键点击或控制单击您的垃圾 545 00:34:13,440 --> 00:34:15,580 或选择“文件”,“清空废纸篓”或任何 546 00:34:15,580 --> 00:34:21,420 你实际上是空的垃圾桶或回收站,到底发生了什么,然后把这张照片吗? 547 00:34:22,810 --> 00:34:25,969 更多的什么都没有。所以没有什么实际发生的磁盘上。 548 00:34:25,969 --> 00:34:30,880 >> 如果我们仅仅是暂时偏离和写 - 我会使用后面的。 549 00:34:30,880 --> 00:34:34,639 所以,现在的故事正在发生变化,从RAM,这是程序存在 550 00:34:34,639 --> 00:34:39,250 而你在运行当中,磁盘,这是他们长期存储 551 00:34:39,250 --> 00:34:42,920 即使在电源熄灭,现在 - 而且在未来,我们会回来的这 - 552 00:34:42,920 --> 00:34:46,380 让我们假装这代表您的计算机硬盘驱动器内 553 00:34:46,380 --> 00:34:50,110 因为在这一天,他们曾经是圆盘,就像软盘。 554 00:34:50,110 --> 00:34:55,130 所以,如果你有一些敏感的Excel文件,它可能需要此内存块的 555 00:34:55,130 --> 00:34:59,770 您的计算机的磁盘上,我只是画相同的任意1s和0s。 556 00:34:59,770 --> 00:35:03,970 当您拖动文件,这样您的垃圾回收站, 557 00:35:03,970 --> 00:35:07,750 从字面上没有任何反应,因为苹果和微软刚决定 558 00:35:07,750 --> 00:35:10,450 垃圾桶,回收站实际上只是一个临时占位符。 559 00:35:10,450 --> 00:35:14,710 也许最终的OS将它清空你的,但通常情况下,它不会做任何事情, 560 00:35:14,710 --> 00:35:17,090 至少要等到你的空间是非常低的。 561 00:35:17,090 --> 00:35:20,870 >> 然而,当你去清空垃圾箱或清空回收站, 562 00:35:20,870 --> 00:35:23,460 同样,什么也没发生这个画面。 563 00:35:23,460 --> 00:35:28,590 所有这一切发生在您的计算机上的其他地方,有一些类型的表。 564 00:35:28,590 --> 00:35:35,400 这有点像一个小小抄说,让我们的说,resume.doc的, 565 00:35:35,400 --> 00:35:40,920 所以你的简历在Microsoft Word文件,用于住在你的硬盘上的位置123, 566 00:35:40,920 --> 00:35:43,710 在内存中,而不是在RAM,但在您的硬盘, 567 00:35:43,710 --> 00:35:49,050 粗略JPEG住在456,和住在789或是其他地方,您的Excel文件。 568 00:35:49,050 --> 00:35:53,640 当你清空垃圾桶或回收站,删除的文件 569 00:35:53,640 --> 00:35:59,530 这幅画并没有改变。在您的硬盘驱动器上的“0”和“1不要去任何地方。 570 00:35:59,530 --> 00:36:03,930 但这个表,这个小数据库的各种变化。 571 00:36:03,930 --> 00:36:08,750 当你删除你的简历,这是因为虽然在一定程度上被删除的文件, 572 00:36:08,750 --> 00:36:12,790 但所有的电脑没有忘记那件事住在您的硬盘驱动器。 573 00:36:12,790 --> 00:36:17,870 您的简历或任何其他文件的0和1组成仍然完好无损。 574 00:36:17,870 --> 00:36:21,960 >> 所以,如果你这样做是偶然,还是有一个非零的概率 575 00:36:21,960 --> 00:36:25,800 使用Norton Utilities或一些商业软件,你可以恢复你的数据 576 00:36:25,800 --> 00:36:29,810 在生活中,其目的是找到“0”和“1”,有几分被孤立, 577 00:36:29,810 --> 00:36:33,300 被遗忘在这里,但离开这里,这样您就可以得到您的数据备份。 578 00:36:33,300 --> 00:36:38,410 或与警方或联邦调查局的法医调查将采取实际的硬盘驱动器 579 00:36:38,410 --> 00:36:42,550 真正的“0”和“1,看像JPEG文件,看起来像Excel文件的模式, 580 00:36:42,550 --> 00:36:46,400 和恢复,即使电脑已经忘记了他们有他们的方式。 581 00:36:46,400 --> 00:36:49,820 因此,唯一的办法真的要删除数据,我们将讨论在未来, 582 00:36:49,820 --> 00:36:54,190 是进行擦洗或擦拭的文件或硬盘 - 583 00:36:54,190 --> 00:36:56,540 你真的不能摆脱的0和1 584 00:36:56,540 --> 00:36:59,440 否则你会从一个GB的硬盘驱动器 585 00:36:59,440 --> 00:37:02,380 和你最终会与一兆字节的硬盘驱动器,如果你不断地被删除, 586 00:37:02,380 --> 00:37:04,380 从字面上看,“0”和“1。 587 00:37:04,380 --> 00:37:06,310 所以,你会怎么做,如果你真的想掩盖你的行迹 588 00:37:06,310 --> 00:37:10,510 的根本问题仍然是,有0和1的磁盘上的? 589 00:37:10,510 --> 00:37:14,930 我看到有人指手划脚,你会实际打开的设备。这将工作。 590 00:37:14,930 --> 00:37:19,600 [笑]但如果这是一种昂贵的解决方案,你会是更合理? 591 00:37:19,600 --> 00:37:23,270 是啊。 >> [学生]覆盖它们。 >>覆盖他们什么呢? >> [学生]其他数据。 592 00:37:23,270 --> 00:37:29,070 其他数据。您可以只是简单地覆盖你的磁盘0或1或全0,全1。 593 00:37:29,070 --> 00:37:31,230 >> 这的确是一些软件的作用。 594 00:37:31,230 --> 00:37:33,570 你可以购买软件,甚至获得免费的软件, 595 00:37:33,570 --> 00:37:36,610 甚至建到Mac OS这些天来,因此在Windows, 596 00:37:36,610 --> 00:37:38,660 是能够安全擦除。 597 00:37:38,660 --> 00:37:41,960 其实,如果你想今天所有的跑回家,如果你有一个苹果,这样做, 598 00:37:41,960 --> 00:37:45,740 如果你有一些东西在你的垃圾,你可以做“安全清倒废纸篓”, 599 00:37:45,740 --> 00:37:47,610 这正是这么做的。 600 00:37:47,610 --> 00:37:53,350 而不仅仅是擦除文件,它不会删除“0”和“1, 601 00:37:53,350 --> 00:38:01,240 相反,它只是改变了他们所有的,例如,0,点,点,点。 602 00:38:01,240 --> 00:38:05,330 因此,你的未来的pset实际上是有意恢复数据 - 603 00:38:05,330 --> 00:38:08,430 我们已经采取了在校园内的人,地,事,物的照片, 604 00:38:08,430 --> 00:38:12,810 为此我们做了法医图像的数码相机的存储卡, 605 00:38:12,810 --> 00:38:17,120 这是同样的想法 - 你将面临的挑战是找到 606 00:38:17,120 --> 00:38:20,160 的模式,代表您的硬盘驱动器上的JPEG, 607 00:38:20,160 --> 00:38:23,610 很像以前的学生,他的电子邮件,我读了几个星期前做 608 00:38:23,610 --> 00:38:25,860 恢复他的妹妹的照片。 609 00:38:25,860 --> 00:38:30,300 为什么我们不采取有5分钟的休息时间,和我们会重组与更多的内存。 610 00:38:33,030 --> 00:38:38,610 因此,这里的事情变得有点令人费解,但是这是一个非常强大的步骤 611 00:38:38,610 --> 00:38:40,480 对理解这项工作的。 612 00:38:40,480 --> 00:38:42,900 这里是了一项名为pointers.c。 613 00:38:42,900 --> 00:38:45,430 这是在今天的示例代码。 614 00:38:45,430 --> 00:38:51,280 请注意,在第几行,19至22日,所有我们正在做的是类似的GetString 615 00:38:51,280 --> 00:38:54,460 并返回一个地址,将其存储在s。 616 00:38:54,460 --> 00:38:58,380 今后的pset甚至3,如果你想要的,但pset的4和 617 00:38:58,380 --> 00:39:01,030 在那里你可以开始把这些培训驱动轮离开自己, 618 00:39:01,030 --> 00:39:04,030 没有任何理由假装字符串不存在了。 619 00:39:04,030 --> 00:39:07,030 这当然是好刚开始说的char *。 620 00:39:07,030 --> 00:39:12,610 >> 顺便说一句,在网上参考和书籍,你可能会经常看到旁边的星号的变量。 621 00:39:12,610 --> 00:39:15,600 你甚至可能看到它的左右两侧的空间。 622 00:39:15,600 --> 00:39:17,680 所有这些都是功能上是正确的。 623 00:39:17,680 --> 00:39:21,180 不过,就目前而言,我们将这种方法的标准化,使超清晰 624 00:39:21,180 --> 00:39:24,000 ,char *是这样说的字符指针。 625 00:39:24,000 --> 00:39:25,680 这是数据类型。 626 00:39:25,680 --> 00:39:28,730 的名称,然后在这种情况下,该变量为s。 627 00:39:28,730 --> 00:39:31,180 因此,我们已经得到了一个字符串,我们调用它s。 628 00:39:31,180 --> 00:39:35,180 然后在这里发现,其实我做的一点点的挂羊头卖狗肉。 629 00:39:35,180 --> 00:39:39,080 这就是所谓的指针的算术运算,这是超级简单的排序。 630 00:39:39,080 --> 00:39:41,790 这只是意味着增加和减少数字的指针。 631 00:39:41,790 --> 00:39:43,660 但是,这实际上是工作的。 632 00:39:43,660 --> 00:39:49,170 这个方案显然打印字符串的第1个字符,每行这样最终的结果 - 633 00:39:49,170 --> 00:39:54,920 正是这样,我们可以尽情这是怎么回事,使指针,运行指针,让我放大。 634 00:39:54,920 --> 00:39:58,940 现在,让我像HELLO类型输入类型 635 00:39:58,940 --> 00:40:01,080 并打印出每行1个字符。 636 00:40:01,080 --> 00:40:04,730 直至一秒钟前,我们就已经做到了这一点用方括号表示。 637 00:40:04,730 --> 00:40:09,760 我们希望有一个for循环,我们会做的printf的s [i]和我们做一遍又一遍 638 00:40:09,760 --> 00:40:11,950 用反斜杠n在每行末尾。 639 00:40:11,950 --> 00:40:16,800 但这种方案是不同的。这个程序使用,从字面上看,算术。 640 00:40:16,800 --> 00:40:18,860 所以这是怎么回事呢? 641 00:40:18,860 --> 00:40:24,720 首先,这个循环执行之前,是什么,仅仅是明确的,是什么呢? 642 00:40:24,720 --> 00:40:27,270 S是吗? >> [学生]的地址。 >>地址。 643 00:40:27,270 --> 00:40:32,980 >> 它的地址,在的情况下,你好,这个词的第一个字符,这是H。 644 00:40:32,980 --> 00:40:37,370 因此,s是,在这个特定的例子中,h的地址。 645 00:40:37,370 --> 00:40:41,850 那么,是什么意思做s +我吗? 646 00:40:41,850 --> 00:40:46,280 嗯,我从0开始,在for循环。我们已经做了很多次。 647 00:40:46,280 --> 00:40:49,760 我是要去的字符串的长度,显然。 648 00:40:49,760 --> 00:40:53,950 因此,在此循环的第一次迭代中,i是明显0。 649 00:40:53,950 --> 00:41:01,740 所以这个表达式是说S + I - 而,S +0,显然只需s。 650 00:41:01,740 --> 00:41:04,320 那么,什么是*吗? 651 00:41:04,320 --> 00:41:08,530 现在,我们在一个稍微不同的方式使用明星。 652 00:41:08,530 --> 00:41:13,080 让我继续前进,摆脱对的,因为我们正在谈论t和s的副本。 653 00:41:13,080 --> 00:41:15,540 现在,我们只是想讲一个故事,涉及小号。 654 00:41:15,540 --> 00:41:20,090 因此,在这一刻,后字符串类型的,我们的世界看起来很喜欢它以前 655 00:41:20,090 --> 00:41:26,630 只需s h和存储地址通常指向的字符串你好。 656 00:41:26,630 --> 00:41:33,170 如果我现在做的像一条线*(S + I),让我们尝试了这一点。 657 00:41:33,170 --> 00:41:40,140 所以*(S + I)。让我简化了这一点,因为这是0,所以这是*(+0)。 658 00:41:40,140 --> 00:41:43,790 好了,等待一分钟。进一步简化。这是*()。 659 00:41:43,790 --> 00:41:47,020 那么,现在的括号是种愚蠢的,所以现在就让我们做*。 660 00:41:47,020 --> 00:41:50,540 因此,在这个循环中,该行突出显示,26的第一次迭代中, 661 00:41:50,540 --> 00:41:53,650 几乎相当于印刷本。 662 00:41:53,650 --> 00:41:56,040 *的数据类型是什么? 663 00:41:56,040 --> 00:42:00,770 在这方面,因为明星恰好是旁边的s本身, 664 00:42:00,770 --> 00:42:04,930 但更特别的是,因为我们不再声明, 665 00:42:04,930 --> 00:42:09,730 我们不创建一个变量了,这里没有提到的char *在第26行, 666 00:42:09,730 --> 00:42:14,280 这里没有提到的关键字串,我们只使用一个变量称为s, 667 00:42:14,280 --> 00:42:19,650 事实证明,现在的明星都有稍微不同的,无可否认,扑朔迷离的意义。 668 00:42:19,650 --> 00:42:26,590 *在这里的意思去做,就这样在s和打印的地址。 669 00:42:26,590 --> 00:42:33,750 所以S是在这里,s是 - 有点像槽和梯子,按照箭头 - 在这里。 670 00:42:33,750 --> 00:42:35,850 因此,这是* S。 671 00:42:35,850 --> 00:42:39,060 >> 那么,什么被印在第一次迭代中,第26行的循环? 672 00:42:39,060 --> 00:42:42,170 我打印出来%,这是一个字符的占位符, 673 00:42:42,170 --> 00:42:48,520 然后一个\ n新行。 *(S + i)其中i为0就是这种。 674 00:42:48,520 --> 00:42:53,670 所以char类型,我将在%C? H. 675 00:42:53,670 --> 00:42:56,900 在接下来的迭代循环 - 你或许可以看到这是怎么回事 - 676 00:42:56,900 --> 00:43:01,350 明显的下一次迭代i是1,所以这意味着s +1个 677 00:43:01,350 --> 00:43:05,580 ,那么现在我需要括号,因为现在的明星需要说 678 00:43:05,580 --> 00:43:08,620 到内存地址+1。 679 00:43:08,620 --> 00:43:14,170 是什么?我们走的时间和说,现在这个箭头是不实际做我们任何好处。 680 00:43:14,170 --> 00:43:18,450 让我们更具体的说,这是存储数量123 681 00:43:18,450 --> 00:43:25,110 此字符串的开始,因为你好,这是地址123,这是124,等等。 682 00:43:25,110 --> 00:43:30,550 因此,在第二次迭代时,我说S +1,这是喜欢说123 +1, 683 00:43:30,550 --> 00:43:35,340 否则为124,所以char类型被印在第二次迭代? 684 00:43:35,340 --> 00:43:37,850 E在内存地址124。 685 00:43:37,850 --> 00:43:44,440 +再次,125,126,127,和这个循环谢天谢地停止之前,我们在这里 686 00:43:44,440 --> 00:43:49,040 因为我使用strlen,以确保我不指望太高。 687 00:43:49,040 --> 00:43:50,810 所以这也是它。 688 00:43:50,810 --> 00:43:55,000 再次,这是就好像我们做了一个星期前。 689 00:43:55,000 --> 00:43:59,200 让我把它写在下面的行,即使我们不希望做两件事。 690 00:43:59,200 --> 00:44:02,500 这是相同的,现在这个。 691 00:44:02,500 --> 00:44:08,310 >> 因此,即使s是一个字符串,因为我们已经调用了几个星期,S是真的一个char *。 692 00:44:08,310 --> 00:44:13,270 因此,如果我们想成为超级肛门,这是很正确的写特定的字符 693 00:44:13,270 --> 00:44:17,490 在第i个位置使用这些数字的地址,这星算, 694 00:44:17,490 --> 00:44:20,470 但坦率地说,这就是这么多的清洁剂。因此,这是不坏的。 695 00:44:20,470 --> 00:44:26,720 没有理由停止在这里做线27,26在功能上是相同的, 696 00:44:26,720 --> 00:44:31,570 它的功能相同的确切原因,我们一直在讨论迄今。 697 00:44:31,570 --> 00:44:33,650 最后,29是良好的做法。 698 00:44:33,650 --> 00:44:38,420 调用free s的,现在你给GetString的给你的内存 699 00:44:38,420 --> 00:44:41,630 这还是因为同样的原因,我提到周一,GetString的几个星期 700 00:44:41,630 --> 00:44:44,180 已经被引入到您的代码中的错误。 701 00:44:44,180 --> 00:44:46,490 你的代码为周有内存泄漏 702 00:44:46,490 --> 00:44:49,970 让你一直问GetString的内存,但你从来没有给它。 703 00:44:49,970 --> 00:44:53,410 而且,我们特意选择了教学法 704 00:44:53,410 --> 00:44:55,880 因为它只是太多认为大约在早期。 705 00:44:55,880 --> 00:44:57,710 但现在我们需要更多的对称性​​。 706 00:44:57,710 --> 00:45:00,830 如果你问电脑的内存,是为getString的情况下, 707 00:45:00,830 --> 00:45:02,820 的malloc的情况一样,显然, 708 00:45:02,820 --> 00:45:07,970 现在,您必须pset的4起,也无任何这样的记忆。 709 00:45:07,970 --> 00:45:11,650 请注意,这是不同的,说廉政n。 710 00:45:11,650 --> 00:45:15,040 你不需要释放,因为你没有调用GetString 711 00:45:15,040 --> 00:45:16,890 你没有调用malloc。 712 00:45:16,890 --> 00:45:20,610 >> 而且,即使你叫调用getInt,因为我们最终会看到, 713 00:45:20,610 --> 00:45:25,520 调用getInt不分配内存给你,因为你可以传递的整数 714 00:45:25,520 --> 00:45:29,430 花车和字符的方式,我们已经做了好几个星期。 715 00:45:29,430 --> 00:45:33,960 字符串,虽然是特殊的,因为实际上他们的串联多个字符。 716 00:45:33,960 --> 00:45:37,450 因此,他们只是不同的字符和浮点和整数等。 717 00:45:37,450 --> 00:45:39,980 但我们会回来的,不久。 718 00:45:39,980 --> 00:45:44,920 任何问题,然后在此开始的指针吗?是啊。 719 00:45:44,920 --> 00:45:49,690 [听不见的学生问题] 720 00:45:49,690 --> 00:45:51,440 啊,非常好的问题。 721 00:45:51,440 --> 00:45:55,790 C实际上为你做的几件事情之一,这是方便, 722 00:45:55,790 --> 00:46:00,110 它计算出你的数据类型的大小是什么 723 00:46:00,110 --> 00:46:03,060 ,然后做那种对你的乘积。 724 00:46:03,060 --> 00:46:06,610 中字符的情况下,这是不相关的,因为几乎总是一个char是1个字节, 725 00:46:06,610 --> 00:46:08,150 所以这只是工作。 726 00:46:08,150 --> 00:46:11,220 但为了讨论的方便,如果你在实际打印整数 727 00:46:11,220 --> 00:46:15,500 你试图打印出一些值,指向一个整数, 728 00:46:15,500 --> 00:46:20,720 你同样不会需要做的+ 4 *我只是因为int是4个字节。 729 00:46:20,720 --> 00:46:25,780 指针的算术平均值的C编译器为你做所有的数学。 730 00:46:25,780 --> 00:46:29,190 所有你关心的是点样的人的感觉。是啊。 731 00:46:29,190 --> 00:46:35,200 [学生]如果你声明一个字符串在一个for循环,你必须释放它吗? 732 00:46:35,200 --> 00:46:36,760 这个问题问得好。 733 00:46:36,760 --> 00:46:41,390 >> 如果你声明一个字符串内的循环,你需要释放它吗? 734 00:46:41,390 --> 00:46:47,520 您只需要你GetString或使用malloc分配的可用内存。 735 00:46:47,520 --> 00:46:53,110 所以,如果你只是说类似 - 让我把花括号,所以现在所有的代码都涉及。 736 00:46:53,110 --> 00:46:58,580 如果你做了,尽管是buggily的,像这样的char * T = S, 737 00:46:58,580 --> 00:47:03,450 你不需要免费的T,因为T不涉及任何提及malloc或GetString的。 738 00:47:03,450 --> 00:47:08,960 GetString时,如果通过对比,你这样做,那么,你将需要免费的T。 739 00:47:08,960 --> 00:47:14,350 而事实上,你唯一的机会做到这一点是在这个循环中,对同一问题的范围 740 00:47:14,350 --> 00:47:16,060 我们已经讨论了过去。 741 00:47:16,060 --> 00:47:18,830 否则,你会被分配内存,分配内存,分配内存, 742 00:47:18,830 --> 00:47:21,230 和在程序结束时,因为你以外的该循环, 743 00:47:21,230 --> 00:47:24,240 t不存在的,但你从来没有告诉操作系统 744 00:47:24,240 --> 00:47:26,750 你并不需要的内存了。 745 00:47:26,750 --> 00:47:30,430 不久,pset的4或5,我们将装备你的程序称为Valgrind的, 746 00:47:30,430 --> 00:47:34,160 这是类似的,它是一个神秘的界面得到了一定程度的精神,GDB, 747 00:47:34,160 --> 00:47:35,750 但它的目的是帮助你在生活中。 748 00:47:35,750 --> 00:47:39,380 和Valgrind是一个程序,将在未来搜索你的程序 749 00:47:39,380 --> 00:47:42,550 查找内存泄漏,无论是从GetString或malloc的, 750 00:47:42,550 --> 00:47:47,800 我们将开始使用更因为我们停止使用尽可能多的CS50库。 751 00:47:47,800 --> 00:47:53,030 现在我们终于有几分的词汇和理论模型中的那种精神 752 00:47:53,030 --> 00:47:55,170 解决这个破碎的程序。 753 00:47:55,170 --> 00:47:59,410 >> 因此,在这个破碎的计划内的交换,交换, 754 00:47:59,410 --> 00:48:05,280 但它从来没有真正的工作,主要是因为主要通过在X和Y,召回, 755 00:48:05,280 --> 00:48:07,260 和那些被传入的值,可以这么说。 756 00:48:07,260 --> 00:48:09,330 副本交换。 757 00:48:09,330 --> 00:48:12,520 年底的交换,确实被交换a和b, 758 00:48:12,520 --> 00:48:16,120 x和y,我们讨论(星期一),但当然不在场。 759 00:48:16,120 --> 00:48:19,940 所以我在这里提出的绿色,这其实是这里的解决方案。 760 00:48:19,940 --> 00:48:22,640 而实际上,让我感动我的星星,只是是一致的 761 00:48:22,640 --> 00:48:24,440 ,即使再次,功能这并不重要。 762 00:48:24,440 --> 00:48:28,730 在未来几周,我们将解释时,为什么它很重要。 763 00:48:28,730 --> 00:48:30,600 因此,在绿色现在是一个解决方案。 764 00:48:30,600 --> 00:48:33,700 坦率地说,它看起来一大堆混乱的,因为我有所有的这些明星。 765 00:48:33,700 --> 00:48:35,380 让我指出一件事。 766 00:48:35,380 --> 00:48:40,040 最上面一行在这里说* A * B 767 00:48:40,040 --> 00:48:42,820 从根本上做同样的事情,因为它总是。 768 00:48:42,820 --> 00:48:47,070 声明的参数或参数交换, 769 00:48:47,070 --> 00:48:49,940 第一,这是一个int指针, 770 00:48:49,940 --> 00:48:53,100 其中第二个是一个int指针调用b。 771 00:48:53,100 --> 00:48:55,770 在这一点上是新的唯一的事实是,有一个明星。 772 00:48:55,770 --> 00:48:59,340 >> 这是什么意思呢?是不是int,b是一个int。 773 00:48:59,340 --> 00:49:04,100 A是一个int和b的地址的地址是不同的诠释。 774 00:49:04,100 --> 00:49:06,980 在这里,这是我承认C得到混乱。 775 00:49:06,980 --> 00:49:09,790 现在我们使用的是一个明星,但在这种情况下有不同的含义。 776 00:49:09,790 --> 00:49:13,150 因为我们并没有声明函数指针,因为我们是在这里, 777 00:49:13,150 --> 00:49:15,500 在这里,我们提领的东西。 778 00:49:15,500 --> 00:49:21,520 所以,在技术上,在此上下文中的第一,第二,和第三线的内部的交换星级 779 00:49:21,520 --> 00:49:24,560 被解引用运算符,它只是意味着去那里。 780 00:49:24,560 --> 00:49:27,400 因此,正如我的手指跟着箭头为h, 781 00:49:27,400 --> 00:49:31,100 *的手段去该地址,找到我的int类型的存在。 782 00:49:31,100 --> 00:49:34,250 * B表示的地址和那里的东西递给我。 783 00:49:34,250 --> 00:49:40,730 因此,让我们重新绘制的图片(星期一)现在使用的栈帧, 784 00:49:40,730 --> 00:49:43,130 其中一个的底部将是主要, 785 00:49:43,130 --> 00:49:47,600 上其中之一将是交换, 786 00:49:47,600 --> 00:49:50,880 所以,我们的世界看起来,就像周一,是这样的。 787 00:49:50,880 --> 00:49:53,620 这里是一大块的内存,主要是要使用。 788 00:49:53,620 --> 00:49:56,520 >> 回想一下,该计划有2个变量, 789 00:49:56,520 --> 00:50:01,930 一个叫x和一个称为y,我已经把数字1和2,。 790 00:50:01,930 --> 00:50:06,580 现在,当我打电话交换一样,我(星期一) 791 00:50:06,580 --> 00:50:11,000 以前我用的是红色版本的这个程序时,它看起来像这样, 792 00:50:11,000 --> 00:50:17,470 我有2个参数,a和b,并没有写在这里和这里? 793 00:50:17,470 --> 00:50:21,160 仅有1和2中,x和y的字面复制。 794 00:50:21,160 --> 00:50:23,070 今天,我们改变这种状况。 795 00:50:23,070 --> 00:50:28,510 今天,而不是传递int类型A和B,我们要通过2个地址。 796 00:50:28,510 --> 00:50:34,290 这些地址正好为整数,但这些地址不是整数。 797 00:50:34,290 --> 00:50:37,330 他们的地址。它像是一个邮寄地址。 798 00:50:37,330 --> 00:50:40,580 所以,现在我们需要的只是给自己多一点细节在屏幕上。 799 00:50:40,580 --> 00:50:43,250 这是我的电脑的内存,因为它整天。 800 00:50:43,250 --> 00:50:45,120 现在,我们需要一些任意的编号方案。 801 00:50:45,120 --> 00:50:50,580 因此,让我们说,只是偶然,这是内存地址123,124。 802 00:50:50,580 --> 00:50:55,660 让我们只说这是125,这是126,等等,但那是完全任意的。 803 00:50:55,660 --> 00:50:58,590 我们只是需要一些在我的记忆中编号方案。 804 00:50:58,590 --> 00:51:04,030 所以,现在当我通过在X和Y,我不打算通过在X和Y; 805 00:51:04,030 --> 00:51:08,400 我要通过邮政地址,可以这么说,x和y的 806 00:51:08,400 --> 00:51:11,870 从而使被存储在这里和这里是1和2, 807 00:51:11,870 --> 00:51:16,030 但如果你能看到我的小文本,通过在这里和这里得到什么? 808 00:51:16,030 --> 00:51:23,340 [听不见的学生回应] >>没错。 123被放在这里,和124被放在这里。 809 00:51:23,340 --> 00:51:28,910 >> 现在,因为我用本的第一行,在这里的明星在上面, 810 00:51:28,910 --> 00:51:34,340 我只知道,123和124,尽管它们显然整数 811 00:51:34,340 --> 00:51:40,160 任何人类可以注意到,他们应该被解释为地址,数字地址。 812 00:51:40,160 --> 00:51:43,250 他们不是在和自己的int类型,他们的地址, 813 00:51:43,250 --> 00:51:46,120 那是因为我已明确地把星星。 814 00:51:46,120 --> 00:51:51,360 所以现在我的第一,第二和第三线的实际代码,这里发生了什么? 815 00:51:51,360 --> 00:51:53,380 让我们绘制的图象的其余部分。 816 00:51:53,380 --> 00:51:56,980 TMP就像是在星期一。没有什么特别的TMP。 817 00:51:56,980 --> 00:52:03,060 这是本地32位变量,和里面的,我的一个显然的值存储。 818 00:52:03,060 --> 00:52:08,580 现在,如果我刚才说的TMP = A,那么我放在这里? >> [学生123。 819 00:52:08,580 --> 00:52:10,370 123。但是,这不是我在做什么。 820 00:52:10,370 --> 00:52:13,670 我说的TMP = * A。星号表示去那里。 821 00:52:13,670 --> 00:52:19,370 因此,这里是123。我怎么去那里?假装有一个箭头。 822 00:52:19,370 --> 00:52:24,460 好了,就在这儿,1。那么,什么被存储在tmp,显然是吗?仅有1。 823 00:52:24,460 --> 00:52:29,620 所以,换句话说,tmp是去的地址,目前正处于一个*,*的手段, 824 00:52:29,620 --> 00:52:31,320 这显然​​是123。 825 00:52:31,320 --> 00:52:33,910 >> 好了,在这里,我们是在位置123,我看到数字1, 826 00:52:33,910 --> 00:52:35,670 所以我打算把1号。 827 00:52:35,670 --> 00:52:39,020 现在,我该怎么办第2行中,* = * B吗? 828 00:52:39,020 --> 00:52:44,570 这是稍微复杂些,因为现在是一个什么呢?这是123。 829 00:52:44,570 --> 00:52:50,220 所以,一个是在哪里呢?在我之前。所以去那里。好吧。 830 00:52:50,220 --> 00:52:53,420 现在,最后,然后终于,这将开始有意义,希望, 831 00:52:53,420 --> 00:53:00,280 * B在B意味着什么? 124。因此,我需要去那里,这是2。 832 00:53:00,280 --> 00:53:03,430 那么,我该怎么放哪里? 833 00:53:03,430 --> 00:53:10,100 2进入这里,因为进入* A * B。所以,我会做到这一点。 834 00:53:10,100 --> 00:53:13,120 你已经可以看到,或许,我们更接近 835 00:53:13,120 --> 00:53:17,710 第一次正确地解决这个愚蠢的,简单的问题 836 00:53:17,710 --> 00:53:20,920 因为现在我们仍然是x的回忆, 837 00:53:20,920 --> 00:53:23,230 我们有2个副本,无可否认,y的, 838 00:53:23,230 --> 00:53:25,850 但现在3号线* B说。 839 00:53:25,850 --> 00:53:31,080 因此,这里的B。 * B的手段去那里。那么,是位置124? 840 00:53:31,080 --> 00:53:35,560 它显然是在这里。所以我把什么呢?显然,tmp目录。 841 00:53:35,560 --> 00:53:39,600 所以,现在我做到这一点。所以,我这里这里。 842 00:53:39,600 --> 00:53:43,560 而现在所有这一切,123,124,和1? 843 00:53:43,560 --> 00:53:47,910 只要交换的回报,这种记忆丢失 844 00:53:47,910 --> 00:53:51,070 因为一旦作为交换的回报,操作系统 845 00:53:51,070 --> 00:53:54,190 在未来再次使用该内存。 846 00:53:54,190 --> 00:53:58,870 只有主内存在这个所谓的堆栈的底部,坚持围绕。 847 00:53:58,870 --> 00:54:01,470 >> 因此,我们现在终于有一个工作版本。 848 00:54:01,470 --> 00:54:06,310 让我去为swap.c,并注意以下几点。 849 00:54:06,310 --> 00:54:11,280 在顶部的程序,我已经改变了我的原型是* A和int * B。 850 00:54:11,280 --> 00:54:15,000 因此,唯一的事情,我改去,这是坏的,从红色到绿色,这是很好的, 851 00:54:15,000 --> 00:54:17,350 是我今天的这些明星。 852 00:54:17,350 --> 00:54:21,520 但再往下在这里交换本身我不得不复制,粘贴只是在幻灯片上。 853 00:54:21,520 --> 00:54:24,140 我在这里有一个明星,明星在这里 - 相匹配的原型 - 854 00:54:24,140 --> 00:54:27,930 然后所有这些事情现在有星星除了TMP 855 00:54:27,930 --> 00:54:30,680 因为使用一个临时变量,有没有什么新东西。 856 00:54:30,680 --> 00:54:33,040 我只是需要临时存储类型为int的。 857 00:54:33,040 --> 00:54:34,820 因此,我们并不需要一个明星。 858 00:54:34,820 --> 00:54:39,310 我们需要的只是明星,这样我们就可以过这种任意边界 859 00:54:39,310 --> 00:54:42,900 这些在我的电脑的内存中的2帧之间。 860 00:54:42,900 --> 00:54:45,630 但最后一件事必须改变,你可能已经瞥见了它。 861 00:54:45,630 --> 00:54:48,810 什么其他的显然是不同的呢? >> [学生]&X。 862 00:54:48,810 --> 00:54:53,270 >> 是啊,所以25是最后一行的代码,我需要改变这个工作。 863 00:54:53,270 --> 00:54:58,360 一个星期前,即使是在星期一的第25行是这样的,交换x和y, 864 00:54:58,360 --> 00:55:02,020 这是刚刚打破,因为如果你说掉期(X,Y) 865 00:55:02,020 --> 00:55:05,660 你给的x和y的副本掉,然后做自己的事情, 866 00:55:05,660 --> 00:55:09,080 但你从来没有真正改变x和y本身。 867 00:55:09,080 --> 00:55:12,880 所以,即使你从来没有见过这个字符与符号的代码, 868 00:55:12,880 --> 00:55:15,860 只是猜测。符号做什么,显然是吗? 869 00:55:15,860 --> 00:55:17,890 [学生]的地址。地址>>注意到。 870 00:55:17,890 --> 00:55:21,160 因此,符号是说给我x的地址。 871 00:55:21,160 --> 00:55:25,590 谁知道它在哪里?它正好是123。我不在乎。只要给我x的地址。 872 00:55:25,590 --> 00:55:28,340 &y表示y的地址给我。 873 00:55:28,340 --> 00:55:34,450 在这一点上的故事是完全一致的图片,我们刚才画。 874 00:55:34,450 --> 00:55:38,310 >> 所以,我得承认指针,当然对我来说,当我第一次开始学习, 875 00:55:38,310 --> 00:55:40,570 绝对包住我的脑海里约最困难的事情之一。 876 00:55:40,570 --> 00:55:43,760 但实现,尤其是我们玩这些事情, 877 00:55:43,760 --> 00:55:48,030 智力无趣的,如果你把它分解到这些超级简单的排序问题 878 00:55:48,030 --> 00:55:52,270 移动数字周围,回答了很多混乱的指针 879 00:55:52,270 --> 00:55:56,590 真的可以来自这些非常基本的力学。 880 00:55:56,590 --> 00:55:59,070 这里有一个地址。去那里的明星。 881 00:55:59,070 --> 00:56:03,830 或者反过来说,这里是一个符号。图的地址实际上是什么。 882 00:56:03,830 --> 00:56:06,270 好的。 883 00:56:06,270 --> 00:56:09,000 那么,此内存来自哪里? 884 00:56:09,000 --> 00:56:12,360 我们已经开了几次这张照片,我一直许诺我们会回来的, 885 00:56:12,360 --> 00:56:14,920 但这里是您的计算机的内存中的代表性 886 00:56:14,920 --> 00:56:17,420 这是多一点比我们的黑板标记。 887 00:56:17,420 --> 00:56:21,590 在顶部的文本段代表你的程序是什么? 888 00:56:21,590 --> 00:56:26,090 [听不见的学生回应] >>你说什么?再说一遍。 889 00:56:26,090 --> 00:56:28,660 [学生]:实际的程序。 >>实际的程序。 890 00:56:28,660 --> 00:56:32,430 >> 因此,“0”和“1您已经编写C代码编译后,然后运行铛 891 00:56:32,430 --> 00:56:35,910 和产生0和1的目的还是藏在内存中 892 00:56:35,910 --> 00:56:38,570 因为当你双击一个图标在您的Mac或PC 893 00:56:38,570 --> 00:56:43,010 像马里奥或运行命令提示符,从磁盘0和1的 894 00:56:43,010 --> 00:56:45,700 获得加载到内存中,计算机可以操纵他们 895 00:56:45,700 --> 00:56:47,540 更迅速地执行。 896 00:56:47,540 --> 00:56:50,880 所以初始化的数据和未初始化的数据,我们不会多谈这些问题, 897 00:56:50,880 --> 00:56:52,420 但这些仅仅是全局变量。 898 00:56:52,420 --> 00:56:54,710 初始化是指全局变量,你给的值; 899 00:56:54,710 --> 00:56:59,300 未初始化意味着,你没有给的值的全局变量。 900 00:56:59,300 --> 00:57:01,900 然后这些环境变量,我会完全挥挥手, 901 00:57:01,900 --> 00:57:04,860 但他们在那里和存储事情,比如你的用户名 902 00:57:04,860 --> 00:57:08,090 和其他类型的低级别的细节。 903 00:57:08,090 --> 00:57:12,880 但最精采的作品是这件事情的栈和堆内存的布局。 904 00:57:12,880 --> 00:57:17,470 堆栈中再次是明确的,是的函数被调用时使用的内存, 905 00:57:17,470 --> 00:57:19,710 每当有局部变量 906 00:57:19,710 --> 00:57:22,120 ,每当有参数被传递。 907 00:57:22,120 --> 00:57:24,490 所有这些都发生在堆栈中。 908 00:57:24,490 --> 00:57:29,570 堆,我们还没有谈到,但猜测谁使用堆。 909 00:57:31,120 --> 00:57:32,690 只是不同的内存块。 910 00:57:32,690 --> 00:57:36,620 它发生在被绘制在顶部,但是这是一个任意的图案公约。 911 00:57:36,620 --> 00:57:41,670 谁的显然已经使用的内存从堆中周吗? 912 00:57:41,670 --> 00:57:44,830 这是技术上你,但间接的。 >> [学生] GetString的。 913 00:57:44,830 --> 00:57:47,950 GetString和malloc的。因此,这里的根本区别。 914 00:57:47,950 --> 00:57:51,300 >> 你知道,在过去的几个星期,如果你需要的内存,只需要声明一个变量。 915 00:57:51,300 --> 00:57:54,560 如果你需要大量的内存,直接在你的函数声明一个数组。 916 00:57:54,560 --> 00:57:59,620 但我们已经把面临的问题是,如果你声明的变量在本地内的功能, 917 00:57:59,620 --> 00:58:05,340 只要在函数返回,会发生什么变化记忆体及变量? 918 00:58:05,340 --> 00:58:09,620 只是它不再是你的,对不对?它只是消失在概念上的排序。 919 00:58:09,620 --> 00:58:13,950 它仍然是物理存在,很明显,但它不再是你的使用权。 920 00:58:13,950 --> 00:58:17,160 这显然​​是有问题的,如果你想在生活中写功能 921 00:58:17,160 --> 00:58:20,440 实际分配内存,不给它立即返回。 922 00:58:20,440 --> 00:58:24,180 举个例子:在生活中的GetString的目的是不知道提前 923 00:58:24,180 --> 00:58:26,390 我要在键盘上输入一个字符串有多大, 924 00:58:26,390 --> 00:58:30,390 但它有能够分配内存来存放大卫你好 925 00:58:30,390 --> 00:58:32,860 或213-248,用户可能会键入。 926 00:58:32,860 --> 00:58:35,280 所以GetString的已使用malloc。 927 00:58:35,280 --> 00:58:38,910 malloc的,因此必须使用的堆栈; 928 00:58:38,910 --> 00:58:40,770 而不是它的使用这个东西称为堆。 929 00:58:40,770 --> 00:58:44,430 有没有什么不同的内存。这不是更快或更慢或类似的东西。 930 00:58:44,430 --> 00:58:46,570 这只是身体在不同的位置。 931 00:58:46,570 --> 00:58:50,120 >> 但是,该规则是在堆上分配的内存的 932 00:58:50,120 --> 00:58:56,180 你将永远不会被带走,直到你调用 - 猜测 - 免费。 933 00:58:56,180 --> 00:59:00,510 与此相反,任何在栈上的内存,你问的只是声明一个数组 934 00:59:00,510 --> 00:59:03,320 或者声明一个变量,如我们已经做了好几个星期, 935 00:59:03,320 --> 00:59:05,640 默认情况下,结束了在堆栈中。 936 00:59:05,640 --> 00:59:09,550 的伟大工程的90%的时间,但对那些罕见的场合 937 00:59:09,550 --> 00:59:12,470 在那里你要分配内存,并保持周围, 938 00:59:12,470 --> 00:59:14,730 然后,你需要使用的malloc之类的函数。 939 00:59:14,730 --> 00:59:19,370 我们使用GetString时,在使用malloc之类的函数。 940 00:59:19,370 --> 00:59:23,300 让我们来看看,这可能分解,然后采取偷看在宾基。 941 00:59:23,300 --> 00:59:25,820 我们会回来的,在未来。 942 00:59:25,820 --> 00:59:29,270 这是一个超级简单的程序,在第2行做什么? 943 00:59:29,270 --> 00:59:33,460 在英语中,这些第2行代码里面做的主吗? 944 00:59:33,460 --> 00:59:35,600 [听不见的学生反应] 945 00:59:35,600 --> 00:59:37,880 小心点。它并没有给我的地址,x或y。 946 00:59:37,880 --> 00:59:41,840 [学生]给出整数的指针。 >>好。给我指向整数的指针。 947 00:59:41,840 --> 00:59:45,130 换句话说,给我2块内存我保持绘图今日,, 948 00:59:45,130 --> 00:59:46,950 即使我现在将其擦除,为方形。 949 00:59:46,950 --> 00:59:50,000 给我2块内存,一个叫X,Y - 950 00:59:50,000 --> 00:59:54,320 刚才我叫s和t - 该内存块的类型是什么? 951 00:59:54,320 --> 00:59:57,160 这将存储地址。 952 00:59:57,160 --> 00:59:59,110 这是int *类型。 953 00:59:59,110 --> 01:00:01,630 >> 因此,一个int的地址最终会住在x, 954 01:00:01,630 --> 01:00:03,860 一个int的地址,最终将居住在y 955 01:00:03,860 --> 01:00:08,460 但最初,x和y的里面是什么?谁知道?垃圾值。 956 01:00:08,460 --> 01:00:10,180 它有什么做用指针。 957 01:00:10,180 --> 01:00:12,720 如果我们没有把东西,谁知道居然有吗? 958 01:00:12,720 --> 01:00:18,950 现在,X。这里发生了什么?这是合法的,因为x是一个指针。这是一个int *。 959 01:00:18,950 --> 01:00:21,870 因此,这意味着我可以把在x一些的内存块的地址。 960 01:00:21,870 --> 01:00:25,120 什么的malloc返回?完美的,它返回地址, 961 01:00:25,120 --> 01:00:28,510 在一个整体的内存块的第一个字节的地址。 962 01:00:28,510 --> 01:00:31,140 多少个字节,这显然是分配,例如,在家电吗? 963 01:00:31,140 --> 01:00:33,510 什么是一个int的大小吗? 4。 964 01:00:33,510 --> 01:00:36,600 如果你觉得回到了1周,这是超级重要的,永远记住, 965 01:00:36,600 --> 01:00:38,870 但在这种情况下,它是有用的知道,4个字节。 966 01:00:38,870 --> 01:00:41,770 因此,这是在堆上分配4个字节 967 01:00:41,770 --> 01:00:46,110 和它的返回地址的第一个我任意。 968 01:00:46,110 --> 01:00:47,700 现在,X是什么做的? 969 01:00:47,700 --> 01:00:52,200 A * X = 42是做什么的? 970 01:00:52,200 --> 01:00:57,150 如果我们的故事在这一点上有X,它看起来像这样一些垃圾的价值, 971 01:00:57,150 --> 01:01:04,120 这是目前一些垃圾值y的,现在在第3行中,我已经分配了4个字节。 972 01:01:04,120 --> 01:01:06,950 基本上,这张照片看起来是这样的。 973 01:01:06,950 --> 01:01:12,010 或者更具体地说,如果这是任意地址123,这是我们的故事现在看起来像。 974 01:01:12,010 --> 01:01:23,940 * X = 42意味着什么呢?这意味着到的地址123,并把42号有。 975 01:01:23,940 --> 01:01:26,220 我不需要画出这些线条,因为我们没有做字符串。 976 01:01:26,220 --> 01:01:29,480 >> 我应该写这样的,和示范的缘故, 977 01:01:29,480 --> 01:01:33,240 42作为一个int种需要一个很大的空间,4个字节。 978 01:01:33,240 --> 01:01:35,960 所以这是发生了什么事,但现在有一个问题。 979 01:01:35,960 --> 01:01:40,580 * Y = 13。这是怎么回事就发生在这里? 980 01:01:40,580 --> 01:01:46,470 问题是,* Y在我们的简化的世界只是意味着到y的地址。 981 01:01:46,470 --> 01:01:48,590 在y是什么?这是一些垃圾的价值。 982 01:01:48,590 --> 01:01:53,150 因此,让我们假设,垃圾的价值是5551212,发疯似的。 983 01:01:53,150 --> 01:01:56,750 * y表示去解决5551212。 984 01:01:56,750 --> 01:02:00,450 这就像在这里。它不存在,例如。 985 01:02:00,450 --> 01:02:05,310 因此,* Y取得13的意思,我想画13。它不存在。 986 01:02:05,310 --> 01:02:08,790 我已经超过了段的黑板。我能得到什么? 987 01:02:08,790 --> 01:02:14,930 这神秘的,因为我试图把在内存中的信息segmentation fault 988 01:02:14,930 --> 01:02:19,470 13日在一个地方,不存在这样的值。 989 01:02:19,470 --> 01:02:23,900 其余的程序可能还行,但直至这一点上它不工作。 990 01:02:23,900 --> 01:02:25,350 所以,我们的尝试讲这个故事。 991 01:02:25,350 --> 01:02:27,830 我们会回来的,一旦我们谈到十六进制。 992 01:02:27,830 --> 01:02:30,290 让我们回去,最后,这个东西叫做Binky, 993 01:02:30,290 --> 01:02:33,710 这使人想起坐在家里玩黏土动画是斯坦福大学的一名教授, 994 01:02:33,710 --> 01:02:36,380 来讲述的正是同样的程序。 995 01:02:36,380 --> 01:02:40,580 这只是约3分钟之久。在这里,我们有Binky。 996 01:02:40,580 --> 01:02:45,030 [男扬声器视频]嘿宾基,醒了。它的时间的指针乐趣。 997 01:02:45,030 --> 01:02:50,080 [宾基]那是什么?了解指针吗?哦,好极了! 998 01:02:50,080 --> 01:02:53,700 [男扬声器]好了,要开始了,我想我们需要一对夫妇指针。 999 01:02:53,700 --> 01:02:57,890 >> [Binky]好吧。此代码分配可以指向整数的指针。 1000 01:02:57,890 --> 01:03:02,220 [男性扬声器]好吧。嗯,我看到了两个指针,但他们似乎并没有指向任何东西。 1001 01:03:02,220 --> 01:03:05,550 [宾基这是正确的。最初,指针不指向任何东西。 1002 01:03:05,550 --> 01:03:09,270 的事情,他们指出,被称为指针对象,并设置他们是一个单独的步骤。 1003 01:03:09,270 --> 01:03:12,330 [男扬声器]哦,对的,正确的。我知道这一点。的指针对象是分开的。 1004 01:03:12,330 --> 01:03:15,630 呃,怎么你分配一个指针对象? 1005 01:03:15,630 --> 01:03:21,510 [Binky]好吧。此代码分配一个新的整数的指针对象,而这部分设置x为指向它。 1006 01:03:21,510 --> 01:03:23,500 [男性扬声器]嘿,看起来更好。 1007 01:03:23,500 --> 01:03:26,030 所以,把它做的东西。 >> [宾基]好吧。 1008 01:03:26,030 --> 01:03:30,300 我会取消引用指针x及其指针存储42。 1009 01:03:30,300 --> 01:03:34,410 这一招,我需要我的魔杖解引用。 1010 01:03:34,410 --> 01:03:38,610 [男性扬声器]你的魔杖提领吗?这是伟大的。 1011 01:03:38,610 --> 01:03:44,230 [宾基]这是代码看起来像什么。我会刚刚成立的数量和... [爆裂声] 1012 01:03:44,230 --> 01:03:46,100 [男性扬声器]嘿,你看,那里去。 1013 01:03:46,100 --> 01:03:50,990 这样做在x取消引用如下的箭头来访问它的指针对象, 1014 01:03:50,990 --> 01:03:53,230 在这种情况下,在那里存储42。 1015 01:03:53,230 --> 01:03:57,630 嘿,尝试用它来存储指针,Y 13号通过。 1016 01:03:57,630 --> 01:04:03,250 [Binky]好吧。我就在这里为Y,13号成立 1017 01:04:03,250 --> 01:04:08,360 然后采取的魔杖提领,只是... [嗡嗡的声音喔! 1018 01:04:08,360 --> 01:04:10,980 [男性扬声器哦,哎,没有工作。 1019 01:04:10,980 --> 01:04:14,870 >> 再说了,Binky,我不认为提领y是一个好主意 1020 01:04:14,870 --> 01:04:17,880 因为指针对象是一个单独的步骤 1021 01:04:17,880 --> 01:04:19,850 我不认为我们曾经做了。 1022 01:04:19,850 --> 01:04:21,770 [Binky]嗯,好一点。 1023 01:04:21,770 --> 01:04:26,640 [男性扬声器]是啊。我们分配的的指针y,但我们从来没有设定它指向一个指针对象。 1024 01:04:26,640 --> 01:04:28,780 [Binky]嗯,很细心的。 1025 01:04:28,780 --> 01:04:30,690 [男扬声器]嘿,你看起来好有,宾基。 1026 01:04:30,690 --> 01:04:34,160 所以你能解决它的指针对象为x,y点呢? >> [宾基]当然。 1027 01:04:34,160 --> 01:04:37,100 我会用我的魔杖指针赋值。 1028 01:04:37,100 --> 01:04:39,070 [男性扬声器]的是,要像以前一样是一个问题吗? 1029 01:04:39,070 --> 01:04:40,840 [Binky]不,这不是触摸指针对象。 1030 01:04:40,840 --> 01:04:44,780 它只是改变一个指针,指向的另一个同样的事情。 [爆裂声] 1031 01:04:44,780 --> 01:04:48,570 [男性扬声器哦,我明白了。 y点为x的同一个地方。 1032 01:04:48,570 --> 01:04:51,140 所以等待。现在,y是固定的。它有一个指针对象。 1033 01:04:51,140 --> 01:04:54,520 所以,你可以尝试的的提领魔杖再次发送13个以上。 1034 01:04:54,520 --> 01:04:58,130 [Binky]嗯,还行。这里“。 [爆裂声] 1035 01:04:58,130 --> 01:05:01,250 [男性扬声器]嘿,你看那个。现在提领对y的作品。 1036 01:05:01,250 --> 01:05:05,200 因为指针共享一个指针对象,他们都看到了13。 1037 01:05:05,200 --> 01:05:06,910 [Binky]是啊,分享。不管。 1038 01:05:06,910 --> 01:05:08,880 >> 所以我们要切换地方,现在呢? 1039 01:05:08,880 --> 01:05:11,420 [男性扬声器哦,看,我们没时间了。 >> [宾基]但是 - 1040 01:05:11,420 --> 01:05:13,880 [男性扬声器,只要记住3个指针的规则。 1041 01:05:13,880 --> 01:05:18,630 1,基本结构是,你有一个指针,它指向指针对象。 1042 01:05:18,630 --> 01:05:23,120 但指针和指针对象是分开的,常见的错误是设置一个指针 1043 01:05:23,120 --> 01:05:25,680 但忘了给它一个指针对象。 1044 01:05:25,680 --> 01:05:29,580 2,指针解引用的指针开始,并遵循其箭头 1045 01:05:29,580 --> 01:05:31,060 访问及其指针。 1046 01:05:31,060 --> 01:05:34,340 我们都知道,这只是工作,如果有一个指针对象, 1047 01:05:34,340 --> 01:05:36,460 种回来规则编号1。 1048 01:05:36,460 --> 01:05:39,870 3,指针赋值一个指针,并将其更改 1049 01:05:39,870 --> 01:05:42,390 作为另一个指针指向相同的指针对象。 1050 01:05:42,390 --> 01:05:45,890 因此,在转让之后,指针将指向的相同指针对象。 1051 01:05:45,890 --> 01:05:47,800 有时,这就是所谓的共享。 1052 01:05:47,800 --> 01:05:50,910 >> 而这一切是它真的。再见。 1053 01:05:50,910 --> 01:05:55,840 这是Binky。这是CS50。我们会下周见。 [掌声] 1054 01:05:55,840 --> 01:05:59,000 >> [CS50.TV]