对于指针学习的一些总结

一、指向的内存空间 VS 对应的内存空间

以int *p = num 举例来说

num++:对num对应的内存空间的值加1

p++:对p对应的内存空间的值加1(加的是步长)

(*p)++:根据p对应的空间里保存的地址找到其对应的空间 = 对p指向的内存空间进行操作

从上面的例子可以总结出:

*p:操作的是p指向的内存空间

p:操作的是p对应的内存空间


二、一维指针、二维指针、三维指针及其间的关系

先来看一个整型变量的储存

0x1000 + 1 = 0x1001 加一个字节的长度

0x1000 + 1 = 0x1004 加一个指针的长度

在这里引出步长的概念,即指加上的数据类型的长度


1.一维指针

int *p = num

p保存的是整型变量的地址

p == &num

*p == num == *(&num)


2.二维指针

int *pp = &p

二维指针pp保存的是一维指针p的地址

p++:0x1000 --> 0x1004

(*pp)++:0x1000 --> 0x1004

pp++:0x2000 --> 0x2004

(**pp++):5 --> 6


因此可以总结出:

num = *p == **pp = *(&num)

&num = p = *pp


3.三维指针

int ***ppp = &pp

三维指针ppp保存的是二维指针pp的地址

(**ppp)++:0x1000 --> 0x1004

可以总结出:

num == *p == **pp == ***ppp == *(&num)

&num = p = *pp == **ppp


三、野指针

1.什么是野指针?

野指针是随机指向一块内存的指针,会导致内存泄漏

2.导致野指针的原因有哪些?

①在定义的时候没有初始化,系统随机分配一块内存,指针没有访问权限

②指向一块已经释放的内存

3.如何避免野指针?

野指针是无法完全避免的,只有平时养成良好的编码习惯才能有效的避免野指针

(1)在指针没有指向的时候,令其指向空

好处:①提醒我们不能对零地址进行操作

           ②方便寻找段错误

(2)给指针赋值时,使用malloc给指针分配空间

以用malloc分配100个字节为例:

#define MAX_SIZE 100

char *ptr = (char *)malloc(MAX_SIZE * sizeof(char));

malloc是在堆空间上分配,返回值为void *(万能指针:可以接收任何指针的值,但是不能做取值操作)

(char *):强制类型转换,转换成char型

sizeof(char):提高代码的移植性,因为不是所有操作平台上的char型都是1个字节


malloc的使用步骤:

①分配内存:(char *)malloc(MAX_SIZE * sizeof))

②检查是否分配成功

if(NULL == ptr)

{

    printf(“malloc error:\n”);

    exit(1);
}

③清空内存中的数据    memset/bzero

#define MAX_SIZE sizeof(char) *MAX_SIZE

memset(ptr,0,sizeof(char) * MAX_SIZE)

bzero(ptr,MAX_SIZE)

④使用内存

⑤释放内存  free(ptr)

⑥重新将指针置成NULL


四、指针的运算

1.指针 +/- 整数:跳指针所指向的数据类型的步长

2.指针 - 指针:两个地址相隔的数据的个数


五、动态分配函数malloc、realloc、calloc

1.malloc的实现原理

malloc()到底从哪里得到了内存空间?答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。

malloc()的工作机制:malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。

2.realloc和calloc的使用方法

①realloc

realloc原型是extern void *realloc(void *mem_address, unsigned int newsize);

使用格式:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。

功能:给一个已经分配了地址的指针重新分配空间,先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

内存使用完毕后,要用free()来释放

②calloc

calloc的函数原型:void *calloc(size_t n, size_t size);

使用格式:str = (char*)calloc(10,sizeof(char));

功能:在内存的动态存储区中分配n个长度为size的连续空间,同时会将分配的内存空间中每一位都置为0,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

内存使用完毕后,同样需要用free()来释放

3.malloc、realloc、calloc的比较

①初始化内存:函数malloc不能初始化所分配的内存空间,而函数calloc能。使用malloc之后需要用memset或bzero将分配的内存空间置为0,而calloc在使用时就已经将内存初始化为0了

②realloc传入的指针必须是已经用malloc、calloc或realloc已经分配过内存的指针

③三个函数在内存使用完毕后都需要调用free()来释放


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值