[音乐播放] 道格·劳埃德:可以这么建议 之前,从这里开始。 如果你还没有看过上的视频 指针,你可能想这样做第一。 因为这段视频是另一种 与指针的工作方式。 因此,它会说话 一些概念 我们覆盖的 指针视频和我们 现在要粉饰他们, 假设他们已经 样的了解。 所以,这只是你公平的警告 如果你看到这个视频 你没见过 指针视频,它可能排序 在你的头上飞一点点。 因此,这可能会更好 看它的顺序。 因此,我们已经见过 方式与指针的工作, 这是我们申报 变量,然后我们 声明另一个变量,指针 变量,指向它。 因此,我们已经创建了一个 使用一个名称的变量,我们 有一个名字创建了第二个变量, 我们点了第二个变量 在第一次。 这种具有 问题虽然,因为它 要求我们确切地知道 多少内存我们 将需要的时刻 我们的编译程序。 这是为什么? 因为我们需要能够以命名或 找出所有可能的变量 我们可能会遇到的问题。 我们可能有可能是一个数组 能够容纳大量的信息, 但它仍然不是 完全足够精确。 如果我们不知道叫什么, 如果我们不知道 多少钱,我们需要在编译的时候? 或者,如果我们的节目会 跑了很长一段时间, 接受各种用户 数据,我们不能真正 估计无论我们是 将需要1000台? 它不喜欢,我们可以 说,在命令行 输入多少个项目 你认为你所需要的。 好吧,如果这猜测是错误的? 动态内存分配 排序可以让我们的方式 要解决这方面的问题。 而它的方式做它 是通过使用指针。 我们可以用指针 可以访问动态 分配的内存,内存, 分配为您的程序正在运行。 这不是分配在编译时。 当你动态分配 内存它来自游泳池 内存被称为堆。 以前,所有的我们已经记忆 一直与在使用过程中 一直在下从池中 的存储器称为栈。 一个好方法一般 保持mind--这条规则 并不总是保持为真, 但几乎差不多 一贯主张true--是任何 时间你给一个变量命名 大概住在堆栈上。 而任何时候你不这样做 给一个变量的名称, 您可以使用动态内存? 分配,它生活在堆上。 那种现在我介绍这是 如果有内存这两个池。 但是你可能已经看到了这 图,这是一般 的表示 看起来是什么样的内存, 而我们不会关心所有 的东西在顶部和底部。 我们关心的是这部分 在此中间,堆和栈。 正如你可以看到 在看这个图, 这其实不是两个 内存单独的池。 这是一个内存共享池 你从哪里开始,在这个视觉 你在底部开始 并开始填补 从与栈的底部,和你 从顶部开始,并开始填充 从上而下的堆。 但它确实是 同一池中,它只是 不同点,不同的地点 在存储器中被分配。 你可以用尽 内存是含 堆一路走 的底部,或具有 栈一路顶端, 或具有堆和栈 见面互相反对。 所有这些可以是条件 导致你的程序 运行内存不足。 所以记住这一点。 当我们谈论 堆和栈 我们真的是在谈论 内存相同的通用块,只 该存储器的不同部分。 那么,我们如何动态地得到 首先分配的内存? 如何我们的计划获得 内存作为它的运行? C井提供了一个调用的函数 malloc的,内存分配器,这 您拨打一个电话来了,你传递 有多少你想要的内存字节。 所以,如果你的程序正在运行 你想要一个整数的运行时, 你可能会马洛克四个字节 内存,malloc的括号四人。 马洛克将通过 翻翻堆, 因为我们是动态 分配内存, 它会回报给你 一个指针,指向存储器。 它不会给你的memory-- 它不给它一个名字, 它给你一个指针。 所以这就是为什么我再次说 这是很重要的,也许 看完球视频 之前,我们得过了头到这一点。 所以malloc的是怎么回事,以 还给你一个指针。 如果马洛克不能给你任何 内存,因为你已经用完了, 它会给你回一个空指针。 你还记得,如果我们发生了什么 尝试取消引用一个空指针? 我们遭受赛格故障,对不对? 这可能不是很好。 所以每次拨打电话 永远的malloc你,总是 需要检查是否 指针它给你回空。 如果是,你需要结束程序 因为如果你尝试取消引用 你要去的空指针 挨段错误 和你的程序是 不管怎样都是崩溃。 那么我们如何做静态 得到的整数。 INT的X. 我们可能已经这样做了 一群倍,对不对? 这将创建一个名为变量 X中住在堆栈中。 我们如何动态地获得一个整数? 诠释星PX等于malloc的4。 或者更准确 我们会说INT星级PX 等于为int的malloc的大小, 只是抛出一些较少 围绕我们的计划幻数。 这将获得对我们 从堆四个字节的存储器, 和指针我们得到 回到它被称为像素。 然后,就像我们已经 以前做的我们 可以提领像素到 访问内存。 我们如何从用户那里得到的整数? 我们可以说INT x等于拿到INT。 这是非常简单的。 如果我们想创建一个数组什么 第X住在堆栈上的花车? 浮stack_array--这就是名字 我们array--方括号中的X. 这为我们创建一个数组 第X住在堆栈上浮动。 我们可以创建float数组 家住堆了。 语法看起来可能 多一点麻烦, 但我们可以说浮法 明星heap_array等于 malloc的x次浮子的尺寸。 我需要足够的空间来容纳 x浮点点值。 所以说,我需要100 花车,或1000彩车。 因此,在这种情况下,这将是 400字节100辆彩车, 或4000个字节为1000辆彩车, 因为每个浮点占用 4个字节的空间。 这样做后,我可以使用 在heap_array方括号语法。 正如我会在stack_array,我 可以单独访问它的元素 使用heap_array零,heap_array之一。 回想起我们可以做到这一点的原因 是因为在C数组的名字 确实是一个指针 该数组的第一个元素。 所以,我们正在宣告一个事实 彩车的堆栈这里阵列 其实是有点误导。 我们真的是在 代码第二行有 还创建一个指向一大块 内存我们那么做了一些工作。 这里的大问题 虽然动态分配内存, 这就是为什么它是真的 重要的是要养成一些好习惯 当你使用它。 不同于静态声明 记忆,你的记忆 不会自动返回到 当你的函数完成系统。 因此,如果我们有主,和 主调用一个函数 女,当f完成不管它做 并返回程序的控制 回存储器的主,所有 使用F是给出回复。 它可以再次使用 通过一些其它方案, 或一些其它功能 被调用后来在主。 它可以再次使用同样的内存了。 如果动态 虽然分配内存 你必须明确地告诉 系统,你就大功告成了。 它会抓住它适合你,这可能 导致一个问题,你跑出来 的存储器。 而事实上,我们有时 这是一个内存泄漏。 有时这些内存泄漏 其实是可以真正毁灭性的 为系统的性能。 如果你是一个经常上网的用户 您可以使用特定的Web浏览器, 我不会指名道姓这里,但 有一些网页浏览器在那里 这是臭名昭著的实际上有 内存泄漏没有得到修复。 如果你离开你的浏览器中打开 在很长的一段时间里,天 和天或数周,你有时 可能会注意到,您的系统 是运行非常,非常缓慢。 和其中的原因是, 浏览器已经分配的内存, 但当时没有告诉系统 它的完成它。 所以留下更少的内存 适用于所有的其他程序 有分享,因为你 leaking--的Web浏览器 程序正在泄漏内存。 我们如何给记忆回来 当我们用它做? 那么幸运的是这是一个 很简单的方法来做到这一点。 我们只是释放它。 有一个所谓的自由功能, 它接受一个指向存储器, 我们是好去。 所以我们可以说我们是在 我们的节目中间, 我们想对malloc 50个字符。 我们想的malloc数组,可以 可容纳50个字符。 而当我们得到的指针回 即,该指针的名字是词。 我们做任何我们 打算做的话, 然后,当我们 我们做的只是释放它。 而现在我们又回到那些50 字节的内存回系统。 其他一些功能可以使用它们。 我们不必担心遭受 内存泄漏,因为我们已经释放了字。 我们已经给记忆回来了, 所以我们做的工作吧。 所以有三个 黄金法则,应该 牢记每当你 动态分配内存 使用malloc。 每个内存块 你的malloc必须释放 你的程序之前完成运行。 现在再次,在家电,或在 这种IDE发生反正你 你 - 当这无论如何都会发生 当你的程序被终止, 所有的内存将被释放。 但它总体上是好的编码 实践总是,当你完成, 释放你所mallocd。 这就是说,只有东西 你已经mallocd应该被释放。 如果静态声明 整数,INT×半结肠, 家住在栈中,你 不那么想免费的​​X。 因此,只有你所事 mallocd应该被释放。 最后,不要随意的东西的两倍。 可导致 另一种奇怪的局面。 所以,你已经一切 mallocd必须被释放。 只有你已经事 的malloc应该被释放。 而且不要随意一些的两倍。 所以,让我们通过一个例子在这里 什么样的一些动态分配 内存可能看起来像混合 在一些静态存储器。 什么可能发生在这里? 看看你是否可以按照 同时,你猜是什么 会发生什么,我们去 通过对代码的所有这些行。 所以我们说INT微米。 这里会发生什么? 嗯,这是非常简单的。 我创建一个名为米的整型变量。 我颜色是绿色, 因为这是颜色 我用我说话的时候 关于整型变量。 这是一个盒子。 这就是所谓的米,你可以 它里面存储的整数。 如果我那么说了什么INT明星? 那么这是非常相似的。 我创建一个盒子叫。 这是能够保持为int 明星,指针为整数。 所以我着色它的绿色十岁上下也是如此。 我知道它有什么 做的整数, 但它本身并不是一个整数。 但是,这几乎是同样的想法。 我创建了一个箱子。 这两个权 现在住在堆栈上。 我已经给了他们俩的名字。 INT星级住宿等于为i​​nt的malloc的大小。 这其中可能有点棘手。 花一秒钟想想你 希望发生这个图上。 INT星级住宿等于为i​​nt的malloc的大小。 嗯,这并不仅仅创建一个框。 这实际上造成了两箱。 它的联系,这也确立 在的关系的点。 我们分配了一个块 内存堆。 请注意右上角方框 那里没有一个名称。 我们mallocd它。 它存在于堆。 但B有一个名字。 这就是所谓的B A指针变量。 那住在堆栈上。 所以这是一块内存 指向另一个。 B包含地址 该内存块。 它不具有一个名字,否则。 但它指向它。 所以,当我们说INT星级住宿等于 整型malloc的大小,即在那里, 该箭头突然出现在 右侧有,那整个事情, 我会让它出现 再次,是什么情况。 所有这一切都发生在 该一行代码。 现在,我们会得到更多一点 简单的一次。 一个等于符号微米。 你还记得什么 等于符号m是? 嗯,这是一个获得M的地址。 还是把更多的示意, 一个点为m。 一个等于湾 行,所以这里的另一个之一。 A等于湾 这是怎么回事发生 到图中这个时间呢? 那么记得, 赋值运算符的作品 通过分配的价值 从右到左侧的值。 因此,而不是一个指向米,现在 指向同一个地方,乙组分。 一个没有指向B,A 指出其中B点。 如果尖到b那会 是一个等于符号湾 而是一个等于b刚 意味着和b是现在 指向相同的地址,因为 的B内仅有一个地址。 现在的一个内是相同的地址。 m等于10,可能的 最简单的事情 我们在一点点实现。 把10箱。 星级住宿等于M PLUS 2,从召回 我们的三分球视频什么明星B表示。 我们将取消引用b和认沽 在该存储单元的一些值。 在这种情况下,12。 因此,当我们取消引用点 记得我们刚出差向下的箭头。 或者换一种说法,我们 去那个内存地址 和我们操纵它以某种方式。 我们把一些价值在里面。 在这种情况下,星级住宿 等于M PLUS 2只 去变量指向B, 到内存指向B, 并把M PLUS 2在那里,12。 现在,我游离B。 当我游离B,会发生什么? 还记得我说的自由的手段。 我说什么时候我游离B? 我做的工作呢,对吧? 我基本上放弃了记忆。 我给它回系统。 我不需要这个了是 就是我要告诉他们,好不好? 现在,如果我说明星 等于11,你大概可以 已经告诉坏事 将要发生在这里,对不对? 事实上,如果我想,我大概 将遭受分割故障。 因为现在,虽然 内存以前是块 是的东西,我有 访问,在这一点 现在我访问内存 是不合法的,我来访问。 当我们大概会 还记得,当我们访问内存 我们不该碰, 这是最常见的原因 一个分割 故障。所以我的计划 会崩溃,如果我试图做到这一点。 所以,这又是一个好主意,以获得良好的 实践和良好的生活习惯根深蒂固 用malloc和free工作时, 这样你就不会遭受分割 ,而您使用的故障 您的动态分配 内存负责任。 我是道格·劳埃德这是CS50。