澳门至尊网站-首页

您的位置:澳门至尊网站 > 免费资源 > 函数中的坑

函数中的坑

2019-10-22 21:15

意气风发写在开端
1.1 本节内容
内部存款和储蓄器填充函数memset()中的坑。

内部存款和储蓄器区域能够分为栈、堆、静态存储区和常量存款和储蓄区,局部变量,函数形参,有时变量都以在栈上得到内存的,它们赢得的点子都是由编写翻译器自动实施的。

二 函数原型

动用指针,大家得以像汇编语言同样处理内部存款和储蓄器地址,C 典型函数库提供了累累函数来兑现对堆上内部存款和储蓄器管理,当中囊括:malloc函数,free函数,calloc函数和realloc函数。使用那一个函数要求包罗头文件stdlib.h。

1 /* 来自man memset */
2 #include <string.h>
3 void * memset(void * s, int c, size_t n);

四个函数之间的有分别,也是有牵连,我们理应学会把握这种涉及,从而编出精炼而火速的顺序。

成效描述:memset()函数用常量c的值填充由指针s所指向的内部存款和储蓄器地址空间的前n个字节的内部存储器空间。

在验证它们具体意思早前,先简单从字面上加以认知,前3个函数有个同步的特性,就是都蕴含字符”alloc”,正是”allocate”,”分配”的情致,也等于给目的分配丰硕的内部存款和储蓄器,” calloc()”是”分配内部存款和储蓄器给五个对象”,” malloc()”是”分配内存给二个目的”,”realloc()”是”重新分配内部存款和储蓄器”之意。”free()”就较易了,”释放”的意思,正是把前面所分配的内部存款和储蓄器空间给释放出来。

DESCRIPTION : The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.

我们能够参照那篇小说:

 

 

参数:
void * s - 指向要被填充的内部存款和储蓄器空间的首地址
int c

void *calloc(size_t nobj, size_t size);

  • 三个常量
    size_t n - 要被填充的字节数

分配足够的内存给nobj个高低为size的靶子组成的数组, 并重回指向所分配区域的首先个字节的指针;

 

若内部存款和储蓄器相当不足,则赶回NULL. 该空间的初阶化大小为0字节.

返回值:
memset()函数是有重回值的,从函数原型也能够看出来。memset()函数再次来到一个对准内部存储器空间s的指针。

char *p = (char *) calloc(100,sizeof(char));

RETURN VALUE : The memset() function returns a pointer to the memory area s.

void *malloc(size_t size);

 

分红充足的内部存款和储蓄器给大小为size的靶子, 并再次回到指向所分配区域的首先个字节的指针;

三 填坑运动
3.1 第八个坑
先举一个memset()正确的施用场景。上边包车型客车代码可以很好地运营,完全能够完结指标。

若内部存款和储蓄器缺乏,则赶回NULL. 不对分配的半空中实行起头化.

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     char Queen[10];
 7 
 8     memset(Queen, 'G', sizeof(Queen));
 9 
10     return 0;
11 }

char *p = (char *)malloc(sizeof(char));

 

void *realloc(void *p, size_t size);

调用memset()函数从前:
(gdb) p Queen
$1 = "36005@000000000024004"
调用memset()函数之后:
(gdb) p Queen
$2 = "GGGGGGGGGG"

将p所指向的对象的深浅改为size个字节.

 

若果新分配的内部存款和储蓄器比原内部存储器大, 那么原内部存款和储蓄器的源委保持不改变, 扩展的上空不开展初始化.

设若Queen数组类型不是char而是int,结果会怎么?

假诺新分配的内部存款和储蓄器比原内部存款和储蓄器小, 那么新内部存储器保持原内部存储器的源委, 扩展的空间不实行初始化.

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     int Queen[10];
 7 
 8     memset(Queen, 'G', sizeof(Queen));
 9 
10     return 0;
11 }

回到指向新分配空间的指针; 若内部存款和储蓄器非常不够,则赶回NULL, 原p指向的内部存款和储蓄器区不改变.

 

char *p = (char *)malloc(sizeof(char));

调用memset()函数早前:
(gdb) p Queen
$1 = {0, 0, 0, 0, 4195824, 0, 4195488, 0, -8352, 32767}
调用memset()函数之后:
(gdb) p Queen
$2 = {1195853639, 1195853639, 1195853639, 1195853639, 1195853639, 1195853639,

p= (char *)realloc(p, 256);

1195853639, 1195853639, 1195853639, 1195853639}

void free(void *p);

观察了啊!Queen数组全体被填充了三个相近的数字,但该数字却不是我们想要的'G'。为啥会那样?道理很简短,memset()函数是贰个字节三个字节地填写数字的,你一个int类型变量在内存中占了4个字节(差别机器,int所占字节数不平等),不出错才怪!上贰个例证之所以能够科学运营,是因为在自个儿的机器上,贰个char类型变量刚好占了贰个字节。

放出p所指向的内部存款和储蓄器空间; 当p为NULL时, 不起效率.

 

p必先调用calloc, malloc或realloc.

怎么防止那个主题材料?下一次记得在行使memset()函数对int型数组进行填充时,所能够运用的常量c的取值只好是0和-1。想想0和-1那多个数的二进制表示是哪些的,你就通晓了为何只好选择那三个数字了。

 

 

值得注意的有以下5点:

3.2 第三个坑
在名利双收逃脱第3个坑之后,你大概还或然会遭遇第4个坑。比方说,你把上述的代码写成了上边包车型大巴那么些样子。

(1)通过malloc函数得到的堆内部存款和储蓄器必须利用memset函数来开始化 

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     int Queen[10];
 7 
 8     memset(Queen, -1, 10);
 9 
10     return 0;
11 }

malloc函数分配获得的内部存款和储蓄器空间是未初叶化的。由此,平时在运用该内存空间时,要调用另一个函数memset来将其开端化为全0,memset函数的扬言如下:void * memset (void * p,int c,int n) ;

 

该函数能够将点名的内部存款和储蓄器空间按字节单地点为钦赐的字符c,当中,p为要清零的内部存款和储蓄器空间的首地址,c为要设定的值,n为被操作的内部存款和储蓄器空间的字节长度。借使要用memset清0,变量c实参要为0。

调用memset()函数早先:
(gdb) p Queen
$1 = {0, 0, 0, 0, 4195824, 0, 4195488, 0, -8352, 32767}
调用memset()函数之后:
(gdb) p Queen
$2 = {-1, -1, 65535, 0, 4195824, 0, 4195488, 0, -8352, 32767}

malloc函数和memset函数的操作语句平日如下:

 

int * p=NULL;

怎么回事,为啥平昔不把Queen数组全部开头化为-1?因为memset()函数是二个字节四个字节地填充数的!第八个参数10意味的是数组Queen中有十个int型数据,它并不表示Queent数组在内存中所占的字节数!精通了吧!

p=(int*)malloc(sizeof(int));

 

if(p==NULL)

怎么幸免这一个主题材料,十分不难,将上述memset()调用改成如下的标准就好了

    printf(“Can’t get memory!n”);

1 memset(Queen, -1, sizeof(Queen));

memset(p,0,siezeof(int));

 

(2)使用malloc函数分配的堆空间在前后相继甘休此前必需释放 

四 仿照效法资料

从堆上得到的内部存款和储蓄器空间在程序甘休现在,系统不会将其活动释放,供给程序猿来本人管理。一个程序停止时,必得保障具备从堆上得到的内部存款和储蓄器空间已被安全释放,否则,会促成内部存款和储蓄器走漏。

  1. man memset

咱俩得以使用free()函数来刑释内部存款和储蓄器空间,不过,free函数只是假释指针指向的开始和结果,而该指针如故指向原本指向的地点,此时,指针为野指针,假诺此刻操作该指针会导致不可预料的荒唐。安全做法是:在行使free函数释放指针指向的半空中之后,将指针的值置为NULL。

(3)calloc函数的分红的内部存款和储蓄器也急需活动释放

calloc函数的功力与malloc函数的功力相近,都以从堆分配内部存款和储蓄器,它与malloc函数的二个明明差异一时候是,calloc函数获得的内部存款和储蓄器空间是经过开首化的,其内容全为0。calloc函数相符为数组申请空间,能够将size设置为数组成分的上空尺寸,将n设置为数组的容积。

(4)借使要动用realloc函数分配的内部存储器,必需运用memset函数对其内存初阶化

realloc函数的功力比malloc函数和calloc函数的功力尤为丰富,能够完毕内部存款和储蓄器分配和内部存储器释放的效果。realloc 能够对给定的指针所指的上空实行扩大恐怕减弱,无论是扩罗恒能缩短,原有内部存款和储蓄器的中剧情将维持不改变。当然,对于收缩,则被压缩的那有个其余开始和结果会舍弃。realloc 并不保证调节后的内部存款和储蓄器空间和原本的内存空间保持意气风发致内存地址。相反,realloc 再次来到的指针很恐怕指向三个新的地点。

所以,在代码中,大家必须要将realloc重返的值,重新赋值给 p :

p = (int *) realloc(p, sizeof(int) *15);

居然,你能够传二个空指针(0)给 realloc ,则此时realloc 效能完全也正是malloc。

int* p = (int *)realloc (0,sizeof(int) * 10);   //分配多少个斩新的内部存款和储蓄器空间,

这大器晚成行,成效完全相像:

int* p = (int *)malloc(sizeof(int) * 10);

(5)关于alloca()函数

再有叁个函数也值得大器晚成提,那就是alloca()。其调用连串与malloc相似,但是它是在眼下函数的栈帧上分红存款和储蓄空间,并非在堆中。其独特之处是:当 函数重返时,自动释放它所利用的栈帧,所以不必再为释放空间而劳累。其症结是:某个系统在函数已被调用后不可能增添栈帧长度,于是也就不可能支撑alloca 函数。纵然如此,超级多软件包照旧使用alloca函数,也可能有为数不菲年体育系扶助它。

本文由澳门至尊网站发布于免费资源,转载请注明出处:函数中的坑

关键词: