0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

memset函数和calloc函数

C语言编程学习基地 来源:C语言编程学习基地 作者:Mr_Li_ 2022-10-20 16:13 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

memset函数

memset(翻译:清零)是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。

以前说过,定义变量时一定要进行初始化,尤其是数组和结构体这种占用内存大的数据结构。在使用数组的时候经常因为没有初始化而产生“烫烫烫烫烫烫”这样的野值,俗称“乱码”。

每种类型的变量都有各自的初始化方法,memset() 函数可以说是初始化内存的“万能函数”,通常为新申请的内存进行初始化工作。它是直接操作内存空间,mem即“内存”(memory)的意思。

该函数的原型为:

## include 
void *memset(void *s, int c, unsigned long n);
将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 c 替换并返回 s

函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。

memset() 的作用是在一段内存块中填充某个给定的值。因为它只能填充一个值,所以该函数的初始化为原始初始化,无法将变量初始化为程序中需要的数据。用memset初始化完后,后面程序中再向该内存空间中存放需要的数据。

memset 一般使用“0”初始化内存单元,而且通常是给数组或结构体进行初始化。一般的变量如 char、int、float、double 等类型的变量直接初始化即可,没有必要用 memset。如果用 memset 的话反而显得麻烦。

当然,数组也可以直接进行初始化,但 memset 是对较大的数组或结构体进行清零初始化的最快方法,因为它是直接对内存进行操作的。

这时有人会问:“字符串数组不是最好用''进行初始化吗?那么可以用 memset 给字符串数组进行初始化吗?也就是说参数 c 可以赋值为''吗?”

可以的。虽然参数 c 要求是一个整数,但是整型和字符型是互通的。但是赋值为 '' 和 0 是等价的,因为字符 '' 在内存中就是 0。所以在 memset 中初始化为 0 也具有结束标志符 '' 的作用,所以通常我们就写“0”。

memset 函数的第三个参数 n 的值一般用 sizeof() 获取,这样比较专业。注意,如果是对指针变量所指向的内存单元进行清零初始化,那么一定要先对这个指针变量进行初始化,即一定要先让它指向某个有效的地址。而且用memset给指针变量如p所指向的内存单元进行初始化时,n 千万别写成 sizeof(p),这是新手经常会犯的错误。因为 p 是指针变量,不管 p 指向什么类型的变量,sizeof(p) 的值都是 4。 (网上找别人的)

#include
#include
int main(void) {
  int i;
  char str[10];
  char *p = str;


  memset(str, 1, sizeof(str));//参数1就是变量名,中间的1就是指定要初始化的值(可以是任意的值包括字符和浮点数)
            //最后那个初始化是长度  (可以是填数字,但没必要)          
  for (i = 0; i < 10; i++) {


    printf("%d	", str[i]);
  }


  return 0;


}

根据memset函数的不同,输出结果也不同,分为以下几种情况:

memset(p, 0, sizeof(p)); //地址的大小都是4字节

0 0 0 0 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(p)); //p表示的是一个字符变量, 只有一字节

0 -52 -52 -52 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(str));

0 0 0 0 0 0 0 0 0 0

memset(str, 0, sizeof(str));

0 0 0 0 0 0 0 0 0 0

memset(p, 0, 10); //直接写10也行, 但不专业

0 0 0 0 0 0 0 0 0 0

calloc函数

有时候,我们在程序中需要一段内存来处理数据,但是又不确定是要多大内存的情况下,比如 我们申请一个数组 a[100] 但是事前我们并不知道会不会用得完这100个元素,比如我们只会用到10个,那么剩下的90个就会还在占用空间,就显得很浪费空间,这时候使用calloc函数是用来在内存的动态存储区中(堆中)分配一个连续存储空间

函数原型:

void* callocunsigned int num,unsigned int size)
在内存的动态存储区中分配num个长度为size的连续空间
num:对象个数,size:对象占据的内存字节数,相较于malloc函数,calloc函数会自动将内存初始化为0

calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不做初始化,分配到的空间中的数据是随机数据。

注意:size仅仅为申请内存字节大小,与申请内存块中存储的数据类型无关,故编程时建议通过以下方式给出,"长度 * sizeof(数据类型)";并不需要人为的计算空间的大小,比如如果他要申请20个int类型空间,就可以int *p = (int *)calloc(20, sizeof(int))这样就省去了人为空间计算的麻烦。

函数返回值:calloc函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

#include
int main(void) {
  int *p = (int *)calloc(10, sizeof(int));
  int i;


  printf("申请得的空间有:
");
  for (i = 0; i < 10; i++) {
    printf("%d ", *p++);
  }


  return 0;
}


结果:
0 0 0 0 0 0 0 0 0 0
//可以看到,使用calloc函数分配时,它最自动赋值零,而下面要介绍的malloc函数则不会

那么会有人有疑问:既然calloc不需要计算空间并且可以直接初始化内存避免错误,那为什么不直接使用calloc函数,那要malloc要什么用呢?

实际上,任何事物都有两面性,有好的一面,必然存在不好的地方。这就是效率。calloc函数由于给每一个空间都要初始化值,那必然效率较malloc要低,并且现实世界,很多情况的空间申请是不需要初始值的,这也就是为什么许多初学者更多的接触malloc函数的原因。

希望对你有帮助

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4421

    浏览量

    67820
  • 数据结构
    +关注

    关注

    3

    文章

    573

    浏览量

    41674
  • 变量
    +关注

    关注

    0

    文章

    616

    浏览量

    29566

原文标题:【零基础学C语言】内存知识总结:memset函数和calloc函数

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    函数信号发生器和任意波形信号发生器区别详解

    函数发生器提供了一个预置列表,里面列出了它可以生成的波形或码型。 在函数发生器中,用户可以更改频率、幅度和偏移等波形参数,还可添加简单的失真。 任意波形发生器更为复杂,能够仿真真实世界中的信号
    的头像 发表于 02-09 16:24 344次阅读
    <b class='flag-5'>函数</b>信号发生器和任意波形信号发生器区别详解

    嵌入式开发常用函数速查表

    在嵌入式开发中,掌握常用函数的用法可以大大提高开发效率。无论是单片机初学者还是有一定经验的工程师,熟悉函数库和调用方式都是必备技能。今天,我们为大家整理一份嵌入式开发常用函数速查表,覆盖GPIO
    的头像 发表于 01-19 09:06 452次阅读
    嵌入式开发常用<b class='flag-5'>函数</b>速查表

    西门子PLC中函数FC的使用方法

    函数函数块作为模块化编程的重要组成部分,在PLC 用户程序中有着相当频繁的应用。两者在生成与使用的过程中都有一定的相似,且都不能单独使用。而需要赋予特定的功能,由组织块(OB)直接或者间接进行调用。
    的头像 发表于 12-19 11:26 4515次阅读
    西门子PLC中<b class='flag-5'>函数</b>FC的使用方法

    函数指针及指针函数的区别

    在学习arm过程中发现这“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,和大家的一些总结,整理到此。和大家分享。   首先它们之间的定义:   1、指针函数是指带
    发表于 12-12 06:34

    如何用函数指针调用函数

    给大家举一个例子: int Func(int x);/*声明一个函数*/ int (*p) (int x);/*定义一个函数指针*/ p = Func; /*将Func函数的首地址赋给指针变量
    发表于 12-11 06:26

    mtf 光学传递函数如何影响图像的质量?

    调制传递函数(MTF):光学系统的“清晰度”度量调制传递函数(ModulationTransferFunction,简称MTF)是光学成像领域中一个核心概念,用于量化成像系统对物体细节的传递能力。它
    的头像 发表于 12-04 16:55 1814次阅读
    mtf 光学传递<b class='flag-5'>函数</b>如何影响图像的质量?

    LUA例程-常用的回调函数使用说明

    详细说明LUA脚本函数功能和对应的应用实例。对于LUA脚本编程有很大的帮助和提高技能。
    发表于 11-24 16:43 0次下载

    使用函数块实现三相电机正反转控制

    在使用西门子S1200PLC,所使用的软件是博途软件,在这个软件里运用了块的概念。比如我们常见的组织块(OB)、函数块(FB)、数据块(DB)以及函数FC等。今天我们来具体交流一下这个函数块(FB)的具体使用方法。
    的头像 发表于 10-15 14:40 2901次阅读
    使用<b class='flag-5'>函数</b>块实现三相电机正反转控制

    加载动态模块报错,提示memset函数未找到,但是代码没用到memset,为什么?

    动态模块提示memset未找到,但是代码没用到memset。 报错: Module: can’t find memset in kernel symbol table
    发表于 10-14 06:59

    大彩讲堂:VisualHMI-LUA教程-set_bit/get_bit函数应用

    set_bit/get_bit函数应用
    的头像 发表于 08-31 17:05 988次阅读
    大彩讲堂:VisualHMI-LUA教程-set_bit/get_bit<b class='flag-5'>函数</b>应用

    大彩讲堂:VisualHMI-LUA教程-on_update回调函数使用指南

    回调函数使用指南
    的头像 发表于 08-31 16:25 1059次阅读
    大彩讲堂:VisualHMI-LUA教程-on_update回调<b class='flag-5'>函数</b>使用指南

    详解hal_entry入口函数

    当使用RTOS时,程序从main函数开始进行线程调度;当没有使用RTOS时,C语言程序的入口函数main函数调用了hal_entry函数。由于我们新建的工程是没有选用RTOS的,因此,
    的头像 发表于 07-25 15:34 2209次阅读

    C语言中的内联函数与宏

    在C编程中,内联函数和宏都用于避免函数调用的开销并编写可复用的逻辑部分,但它们在工作方式和安全性方面存在显著差异。
    的头像 发表于 07-25 15:10 2050次阅读
    C语言中的内联<b class='flag-5'>函数</b>与宏

    深入理解C语言:函数—编程中的“积木块”艺术

    在编程的世界里,函数就像建筑中的“积木块”——它们是构建复杂程序的基石。通过灵活组合这些模块,开发者能打造出功能强大且结构清晰的代码。函数之所以成为C语言的核心,正是因为它解决了编程中的三大关
    的头像 发表于 06-30 17:26 2026次阅读
    深入理解C语言:<b class='flag-5'>函数</b>—编程中的“积木块”艺术

    MSP430常用内联函数说明

    电子发烧友网站提供《MSP430常用内联函数说明.docx》资料免费下载
    发表于 06-05 17:20 0次下载