2.指针(链表定义)
数组指针和指针数组
数组的指针(即数组指针)是指针;
指针的数组(即指针数组)是数组;
数组指针是指向数组的指针;
指针数组是数组元素均为指针。
*数组指针(p)[ ]
#include<stdio.h>
int main()
{
//⼀维数组
int a[5]={1,2,3,4,5};
int b=0;
//步长为5的数组指针,即数组⾥有5个元素
int(*p)[5];
int*q=&b;
//把数组a的地址赋给p,则p为数组a的地址,则*p表⽰数组a本⾝
p =&a;
//%p输出地址, %d输出⼗进制
//\n回车
//在C中,在⼏乎所有使⽤数组的表达式中,数组名的值是个指针常量,也就是数组第⼀个元素的地址,它的类型取决于数组元素的类型。printf("%p\n", a);//输出数组名,⼀般⽤数组的⾸元素地址来标识⼀个数组,则输出数组⾸元素地址
printf("%p\n", p);//根据上⾯,p为数组a的地址,输出数组a的地址
printf("%p\n",*p);//*p表⽰数组a本⾝,⼀般⽤数组的⾸元素地址来标识⼀个数组
printf("%p\n",&a[0]);//a[0]的地址
printf("%p\n",&a[1]);//a[1]的地址
printf("%p\n", p[0]);//数组⾸元素的地址
printf("%d\n",**p);//*p为数组a本⾝,即为数组a⾸元素地址,则*(*p)为值,当*p为数组⾸元素地址时,**p表⽰⾸元素的值1
printf("%d\n",*p[0]);//根据优先级,p[0] 表⽰⾸元素地址,则*p[0]表⽰⾸元素本⾝,即⾸元素的值1
printf("%d\n",*(*p+1));
printf("%p\n",q);
printf("%p\n",&b);
printf("%d\n",*q);
return0;
}
数组指针也称指向⼀维数组的指针,所以数组指针也称⾏指针。
指针数组*p[ ]
#include<stdio.h>
int main()
{//将⼆维数组赋给指针数组
int*pp[3];//⼀个⼀维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2],所以要分别赋值
int c[3][4],i,j;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
scanf("%d",&c[i][j]);
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
printf("%5d",c[i][j]);
printf("\n");
}
printf("\n");
for(i =0; i<3; i++)
pp[i]=&c[i][0];
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
printf("%5d",*(pp[i]+j));;
printf("\n");
}
return0;
}
变量的指针就是变量的存储地址,指针变量就是存储指针的变量。
指针与整数的运算
1. 赋值运算
赋值时可以取变量地址赋值(p=&n),也可以直接将地址赋值(p=65234)。
2. ⾃增⾃减运算
指针加 1 或减 1 运算,表⽰指针向前或向后移动⼀个单元(不同类型的指针,单元长度不同)。
指针变量加上或减去⼀个整形数,加⼏就是向前移动⼏个单元,减⼏就是向后移动⼏个单元。
3. 关系运算
设指针变量 px和py。
px > py
表⽰ px 指向的存储地址是否⼤于 py 指向的地址
px == py
表⽰ px 和 py 是否指向同⼀个存储单元
px == 0 和 px != 0
表⽰ px 是否为空指针
4. 与数组的运算
定义⼀个数组
int num[2] = {1, 3};
将数组中第⼀个元素地址和第⼆个元素的地址赋值给两个指针
int *px = x[0], *py = x[1]; int *pz = x[0]; int *pn;
py > px
py 指向的存储地址⼤于 px 所指向的存储地址;
pz == px
px 和 pz 指向同⼀个地址;
pn 没有初始化
pn == NULL || pn == 0
pn 是⼀个空指针;
##指针与数组
定义⼀个数组,数组名就是该数组的⾸地址。
在定义数组是系统为该数组分配了连续的⼗个相应⼤⼩的空间。
指针作为函数的参数
指针变量也属于变量,作为函数的形参,也需要开辟内存空间,只不过当以指针作为函数形参时,存放的是实参的地址。
所以,实参和形参就是两个保存着相同地址的不同空间。
⼏个知识点
1. 只使⽤指针变量时,加“ * ”代表访问指针p所指向的空间⾥⾯的数据,访问的是别⼈的数据。
2. 不加“ * ”,代表访问的是⾃⼰空间⾥存的数据,访问的是⾃⼰的数据。
指针与二维数组3. *p(指针变量名) = 数据
//这条语句代表给p所指向的空间赋值。
4. 定义⼀个结构体指针 p,将⼀个结构体变量的变量名赋给指针p,则p指向的是结构体的⾸地址,如果对想通过结构体指针p来访问该
结构体变量的成员,就需要进⾏节引⽤运算,即 (*p). 。
5. 指针变量初始化⼀个有效值才可使⽤。
6. 数组存放的内容为普通变量,则数组名为变量的指针;
7. 数组存放的内容为指针,则数组名为指针的指针(⼆级指针)。
链表存储空间的申请与释放
1. 申请存储空间函数malloc
malloc()函数原型为
void *malloc(unsigned int size);
函数值为指针类型,由于其原本返回类型为void,如果要将这个指针赋给其他类型的指针变量,应当进⾏强制类型转换。
int p=(int)malloc(sizeof(int));
这条语句意思是申请⼀个int型长度⼤⼩的存储空间,并将分配到的空间的地址转换为int类型地址,并赋给指针变量p。
2.申请存储空间函数calloc()
calloc()函数原型为
void *calloc(unsigned int n,unsigned int size);
这个函数的功能是申请n个长度的为size字节的存储空间,并返回该存储空间的起始地址。主要⽤于动态数组申请内存空间。
void *p=(int *)calloc(10,sizeof(int));
这条语句含义是:申请10个int⼤⼩的内存空间,并将存储地址转化为int类型,并将其赋给指针p。
3.释放存储空间函数
free()函数原型:
void free( void *p);
这个函数的功能是将指针p所指向的内存空间释放掉,⽆返回值。
且p只能是程序中最后⼀次调⽤malloc或calloc函数所返回的地址。若发⽣改变,编译器会报错。
链表的⼏种使⽤
单链表
特点:
1. 有⼀个head指针变量,即头指针。(头指针表⽰是哪⼀个链表,可⽤于区分)
2. 链表的每⼀个节点都分为数据域和指针域两部分。
3. 链表的最后⼀个节点指向NULL,表⽰结束。
4. 链表中各节点并不是在⼀块连续的内存中存放的,它的各个元素分布与各个地⽅,通过指针指向其地址来访问数据。
5. 链表不受变量定义中的长度限制(仅受内存总量的限制)。
6. 在插⼊和删除操作中,只需要修改相关节点指针域的指向即可。
7. 头指针head永不改变。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论