返回介绍

用 malloc() 申请存储器……

发布于 2024-10-10 23:21:29 字数 4398 浏览 0 评论 0 收藏 0

申请存储器的函数叫

malloc() ,是 memory allocation(存储器分配)的意思。malloc() 接收一个参数:所需要的字节数。通常你不知道确切的字节数,因此 malloc() 经常与 sizeof 运算符一起使用,像这样:

sizeof 告知某种数据类型在系统中占了多少字节。这种数据类型可以是结构,也可以是 int 或 double 这样的基本数据类型。

malloc() 函数为你分配一块存储器,然后返回一个指针,指针中保存了存储器块的起始地址。那么这个指针是什么类型呢?事实上,malloc() 返回的是通用指针,即 void* 类型的指针。

……用 free() 释放存储器

一旦在堆上创建了存储器,就可以随时使用它。一旦完成了工作,就需要用 free() 函数释放存储器。

free() 需要接收 malloc() 创建的存储器的地址。只要告诉 C 标准库存储器块从哪里开始,它就能查阅记录,知道要释放多少存储器。假如想要释放上面那行代码分配的存储器,可以这样做:

好了,现在我们对动态存储器有了更深的了解,可以开始写代码了。

不好!兼职演员来了……

这群有抱负的演员又有一部戏杀青了,所以他们有时间来帮你写代码。他们写了一个实用函数,函数根据你传给它的名字创建新的 island 结构:

这个函数看起来很酷。演员们发现岛上大部分机场的开关门时间相同,所以他们把 open 和 close 字段设为了默认值,函数返回一个指针,指向新创建结构。

脑力风暴

仔细观察 create() 函数的代码,你认为会有问题吗?好好想一想,然后再翻页。

消失的岛屿案件

航空日志:11:00,周五,晴。我们编写了 create() 函数,它动态分配存储器。软件组的人说它可以用于试飞。island* create(char *name){ island *i = malloc(sizeof(island)); i->name = name; i->opens = "09:00"; i->closes = "17:00"; i->next = NULL; return i;}








14:15,多云,百慕大附近,方向西北,每小时 15 海里,逆风飞行。我们在第一站降落,软件组提供了基本的代码,我们在命令行中 入了岛名。

14:45,发生地震,飞机在起飞时发生了轻微的摇晃。软件组在飞机上待命,可乐供给不足。

15:35,到达第二座岛,天气晴朗,无风。在程序中输入信息。

17:50,返回总部,整理日志。奇怪的事发生了,测试程序生成的飞行日志似乎出了错。程序记录了今日的行程,但第一座岛的名字莫名其妙地修改了,赶快让软件组来调查此事。

第一座岛的名字怎么了?create() 函数出错了吗?你能从调用函数的代码中看出端倪吗?

消失的岛屿案件

第一座岛的名字怎么了?

再看一遍 create() 函数:island* create(char *name){ island *i = malloc(sizeof(island)); i->name = name; i->opens = "09:00"; i->closes = "17:00"; i->next = NULL; return i;}








当代码记录岛名时,并没有接收一份完整的 name 字符串,而只是记录了 name 字符串在存储器中的地址。这有关系吗?name 字符串在哪里?为了回答这两个问题,我们看一眼调用 create() 函数的代码。char name[80]; fgets(name, 80, stdin); island *p_island0 = create(name); fgets(name, 80, stdin); island *p_island1 = create(name);




程序要求用户输入每座岛的名字,但两次它都使用本地的字符数组 name 来保存岛名,也就是说两座岛共享同一个 name 字符串,一旦局部变量 name 更新为第二座岛的名字,第一座岛的名字也就改变了。

聚焦字符串复制

在 C 语言中,经常需要复制字符串。你可以调用 malloc() 函数在堆上创建一些空间,然后手动把字符串的所有字符复制到堆上。但你猜怎么着?其他程序员早就想到了,他们在 string.h 头文件中创建了一个叫 strdup() 的函数。假设你有一个指向你想复制的字符串常量的指针:char *s = "MONA LISA";
strdup() 函数可以把字符串复制到堆上:char *copy = strdup(s);

strdup() 函数计算出字符串的长度,然后调用 malloc() 函数在堆上分配相应的空间。

然后 strdup() 函数把所有字符复制到堆上的新空间。

也就是说,

strdup() 总是在堆上创建空间,而不是在栈上,因为栈用来保存局部变量,而局部变量很快就会被清除。因为 strdup() 把新字符串放在堆上,所以千万记得要用 free() 函数释放空间。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文