关于C语言二级指针正确使用总结
什么是二级指针
C语言中的二级指针其实就是指向指针的指针,指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。同理可以构建三级或者N级指针,但是一般情况下用不到多级指针,只有二级指针在一些情况中需要使用,以下是二级指针的初始化:
二级指针的示意图
include <stdio.h>
int main(void)
{
int var;
int *ptr1;
int **ptr2; //初始化一个整型的二级指针
var = 50;
ptr1 = &var; /*获取var的地址*/
ptr2 = &ptr1; /*获取ptr1的地址*/
printf("var 的值是:var = %d\n", var);
printf("var 的值是:*ptr1 = %d\n", *ptr1);
printf("var 的值是:**ptr2 = %d\n", **ptr2);
return 0;
}
编译以后的结果是:
var 的值是:var = 50
var 的值是:*ptr1 = 50
var 的值是:**ptr2 = 50
什么时候该使用二级指针作为函数形参
- 传递指针数组
在C语言中,数组与其它变量在使用上有很大的不同.无论是字符型、整型、实型变量,还是结构体类型或者指针类型的变量,语句中出现变量名都代表对该变量所在内存单元的访问,变量名代表整个变量在内存中的存储单元,可以向该变量赋值,也可以从中取出数据使用.但是定义一个数组之后,数组名并不代表整个数组所占据的内存单元,而是代表数组首元素的地址:
int function1(int **arary);
/*其中array是一个指针数组,元素是指针*/
int *arary[10]; //初始化一个指针数组
function(&arary);
- 对传入的一级指针进行修改
二级指针在数据结构使用比较广泛,因为一些基础的数据结构中很多结构的初始化操作都是以建立一个头结点开始的,比如说在树中,通过调用函数对整体树的结点元素进行操作:改变结点的指向、结点的内存的释放以及结点内存的分配。这时就需要用到指向指针的指针。
我们以二叉树初始化函数为例,其中输入的参数为指向根节点的指针,为了给初始化的根节点指针分配内存就需要一个指针指向根节点指针:
typedef char ElemType;
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild; //左子树&右子树
}BiTNode, *BitTree;
/**创建一个树*/
/*其中T是指向一个根节点指针的指针*/
/*如果此时只是传入根节点指针,那么只是传入根节点指针的副本,函数内的*/
/* 所有操作都是针对副本而言,因此对于这个函数就为该副本开辟了内存,而实际上*/
/* 根节点并没有分配到到内存*/
void CreateBitTree(BitTree *T);
{
ElemType c;// 创建根节点元素
scanf("%c", &c);
if(' ' == c) //无元素输入指针指向空
*T = NULL;
else
{/*否则为树的结点分配空间*/
*T = (BiTNode *)malloc(sizeof(BiTNode));
(*T)->data = c;
CreateBitTree(&((*T)->lchild)); //递归实现树的结点不断初始化
CreateBitTree(&((*T)->rchild));
}
}
以指针参数申请动态内存的错误示例
# include <stdio.h>
# include <stdlib.h>
void Iinitara(char * str, int num)
{
str = (char *)malloc(sizeof(char) * num);
}
int main()
{
char *str = NULL;
Iintara(str, 100);
strcpy(str, 'Hello World'); // 无法实现,因为main函数中的str并为分配到内存
return 0;
}
总结
- 如果修改实参指针指向时就需要用到二级指针
- 如果传入参数是一级指针数组时需要用到二级指针
- 如果只是用指针修改指向单元内容时,只需要传入一级指针即可