指针和数组(一维,二维,三维)以及野指针的避免
来源:互联网 发布:制造业数据采集 编辑:程序博客网 时间:2024/05/07 07:31
如何避免野指针?
答:①当指针未指向时,一般将指针置为空
②当想向指针指向空间赋值时,为其分配空间。当用malloc为其分配空间的时候,要看其是否分配成功(注意清空原来的缓冲区),函数执行完以后,需要用free(ptr),用完后再赋值为NULL(ptr=NULL)
初始化为NULL的目的:①该指向0地址,操作不能在0地址操作②当出现段错误的时候,容易改错,方便调试(NULL为宏,#define NULL (void *)0代表0地址,0地址是不允许操作和访问的)
malloc分配空间:ptr=(char *)malloc(MAX_SIZE*sizeof(char))()加强制类型转换是为了:该必须是相同的
void *:表示万能指针(可接收任何指针类型,但不能进行取值,不能对地址指向空间操作)
指针-指针:计算两地址之间相差多少数据
数组 [ ]=*( )
一维数组(char *p=a)
①scanf(“%d”,&a[i]) scanf(“%d”,a+i) scanf(“%d”,p+i) scanf(“%d”,&p[i]) scanf(“%d”,p++)
②printf(“a[%d]=%d\n”,i,a[i]) printf(“a[%d]=%d\n”,i,*(a+i)) printf(“a[%d]=%d\n”,i,*(p+i)) printf(“a[%d]=%d\n”,i,p[i]) printf(“a[%\n”,i,*p++)
&a:对一维数组的数组名取地址等于数组的地址
*(&a):对一维数组的地址取值等于数组首元素的地址
(int (*pa)[MAX_SIZE]=&a)
二维数组(行可省略)
int a[i][j]
a代表首个一维数组的地址
①scanf(“%d”,&a[i][j]) printf(“a[%d][%d]=%d\n”,i,j,a[i][j])
②scanf(“%d”,*(a+i)+j) printf(“a[%d][%d]=%d\n”,i,j,*(*(a+i)+j)
传二维数组名用一维数组指针来接(void ch(char (*src)[100]))
*(*(a+i)+j)
a+i:第i+1个一维数组的地址
*(a+i):第i+1个一维数组的首元素地址
*(a+i)+j:第i+1个一维数组的第j+1个元素的地址
*(*(a+i)+j):第i+1个一维数组的第j+1个元素的值
三维数组(二维数组指针)
*(&a)=a:对二维数组的地址取值等于首个一维数组的地址
*(*(*(a+i)+j)+k)
a+i:第i+1个二维数组的地址
*(a+i):第i+1个二维数组的首个一维数组的地址
*(*(a+i)+j:第i+1个二维数组的第j+1个一维数组的首元素的地址
*(*(a+i)+j)+k:第i+1个二维数组的第j+1个一维数组的第k+1个元素的地址
*(*(*(a+i)+j+k):第i+1个二维数组的第j+1个一维数组的第k+1个元素的值
传指针数组时,用指针的指针:void print_ptr(char **ptr)
malloc,realloc,calloc的声明:
void* realloc(void* ptr, unsigned newsize);
void* malloc(unsigned size);
void* calloc(size_t numElements, size_t sizeOfElement);
分别什么时候使用?
malloc用于申请一段新的地址,参数size为需要内存空间的长度
calloc与malloc相似,参数sizeOfElement为申请地址的单位元素长度,numElements为元素个数
realloc是给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度
三者的区别:
malloc调用形式为(类型*)malloc(size):在内存的动态存储区中分配一块长度为“size”字节的连续区域,返回该区域的首地址。
calloc调用形式为(类型*)calloc(n,size):在内存的动态存储区中分配n块长度为“size”字节的连续区域,返回首地址。
realloc调用形式为(类型*)realloc(*ptr,size):将ptr内存大小增大到size。
malloc函数原理:
malloc函数有一个将可用的内存块连接为一个长长的列表的所谓空闲链表,调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块,然后将该内存块一分为二(一块的大小与用户申请的大小一样,另一块就是剩下的字节),接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话),返回到链表上,调用free函数 时,它将用户释放的内存块连接到空链上,到最后,空闲链表会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可能满足用户要求的片段了,于是malloc函数请求延时,并开始在空间中翻箱倒柜的检查内存片段,对它们进行整理,并将相邻的小空闲块合成较大的内存块
数组与指针的区别:
区间分配:
①数组要么在静态存储区被创建,要么在栈上被创建。数组名对应着一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
②不能对数组名进行直接复制与比较
访问效率:
通过 a 访问,系统只需要计算常量 a 与 i*sizeof(type) 之和,然后访问该地址
通过 p 访问,p 是个变量,系统必须先访问 p 的地址,得到 p 的值,然后计算该值 v(p) 与 i*sizeof(type) 之和, 然后再访问得到的地址。
相比之下,指针要稍微慢一些,在绝大多数情况下,指针与数组相比,没有效率上的优势,有时反而更慢。指针的真正优势是灵活,好用。
函数传参:
数组在作为函数传参时,数组名将蜕化为指针,二维数组的存储方式是和一维数组没什么区别,但是用二维数组做参数,要注意的是:函数中的形参其实就相当于一个声明,并不产生内存分配,形参的目的就是要让编译器知道函数参数的数据类型
指针传参传递的是一参数(这里是Int实参)的地址,这样,虽然实参和形参不一样,但是它们只想的地址是一样的,所以对相同地址的数的操作会影响到原来的数。
安全性:
指针可能会重复释放,而且会产生野指针,从而导致内存的泄漏;也有可能导致堆缓冲区溢出
- 指针和数组(一维,二维,三维)以及野指针的避免
- 二维数组指针和一维数组指针的区别
- 1.如何避免野指针2.获取字符串的两种方法。以及malloc,calloc,ralloc的使用注意点3.二维三维数组4.数组和函数的区别
- 三维数组和三维数组的指针
- 一维指针和数组,二维指针和数组
- 关于二维数组和一维指针数组的区别
- 一维指针和二维指针指向二维数组的一些问题
- 一维数组,二维数组,三维数组,数组与指针,结构体数组,通过改变指针类型改变访问数组的方式
- C语言 通过指针访问一维数组,二维数组,三维数组。
- 指针以及二维数组
- 指向一维数组的指针变量和指向二维数组的指针变量---注意其指针表示
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 二维数组和指向指针的指针
- 杭电OJ2024-C语言合法标识符
- 整棵树上节点间的最大距离
- 仅此记录所学所感
- DP DPI SP PPI 辨析
- 复杂链表的复制
- 指针和数组(一维,二维,三维)以及野指针的避免
- js学习第一天
- Mac上更新Ruby
- final,多态,抽象,接口
- 20160713 程序流程控制
- PAT 1001 Public Bike Management
- Path Sum II
- Android framework中已经包含support v4
- 智能卡——安全状态&安全属性