c笔记之指针.docx
- 文档编号:24719150
- 上传时间:2023-05-31
- 格式:DOCX
- 页数:33
- 大小:24.87KB
c笔记之指针.docx
《c笔记之指针.docx》由会员分享,可在线阅读,更多相关《c笔记之指针.docx(33页珍藏版)》请在冰豆网上搜索。
c笔记之指针
指针
指针乃地址也。
变量的地址:
系统为变量分配的内存单元的地址(一个无符号的整型数)
变量--存储内容:
数据值
空间大小:
数据类型
空间位置:
地址
生存周期:
存储类别
变量的访问方式:
直接访问
间接访问
指针变量:
是存放地址的变量,该变量是一个地址(无符号的整型数)
eg:
p为指针变量,它存放整型变量a的首地址
则,指针变量p指向整型变量a
指针变量的定义和引用
1.定义方法
类型符*指针变量名
eg:
int*p1,*p2;
char*ps;
float*pf1,pf2;
指针变量的类型--〉是所指向的内存中存放的数据的类型。
2.赋值
指针变量的值为地址,是个无符号整数。
但不能直接将整型常量赋给指针变量。
1.用变量的地址给指针变量赋值(求地址运算符&)
eg:
inta,b,*p;
p=&a;
变量的类型必须与指针变量的类型相同。
p=123;×p指向地址,不是常量或变量
p=&123;×123是常量,常量没有存储空间,就不可能取地址
*p=123;×不知道指针地址,怎么确定的指针内容?
2.用相同类型的指针变量赋值
eg:
inta;
int*p1,*p2;
p1=&a;
p2=p1;
若不赋值,则指针变量的值是随机的。
---危险(死机...)
3.赋空值NULL
eg:
int*p;
p=NULL;或p=0;
4.指针变量的初始化方法
1.赋空值NULL
eg:
int*p1=NULL;
2.用已定义的变量的地址
eg:
floata;
float*p2=&a;
charch,*p3=&ch;
3.应用
1.两个有关的运算符:
*、&
形式:
&任意变量-->取地址运算符
*指针变量-->指针运算符
含义:
&a表示变量a所占据的内存空间的首地址--一般变量
*p表示指针变量p所指向的内存中的数据--指针变量
inta,*p;p=&a;-->*p相当于a
应用:
通过指针变量访问所指变量(通过指针变量间接访问某一个变量)
将指针变量指向被访问的变量
eg:
inta=5,*p,b;
p=&a;
访问所指变量
取内容:
b=*p;-->*p相当于=a
b=*p;//间接访问<==>b=a;//直接访问
printf("%d\n",*p);
存内容:
*p=100;
注意:
*p若出现在“=”的右边或其他表达式中,则为取内容。
*p若出现在“=”的左边,则为存内容。
注意区分:
intb,*p1,*p2=&b;
1.p1=p2;与*p1=*p2;
p1=p2;//把p2的地址赋给p1,p1和p2的地址都指向了b。
*p1=*p2;//把p2所指向的内容放到p1内容里,p1和p2得内容都等于b的内容(b的值)
2.(*p1)++;与*p1++;
(*p1)++;//*p1<==>a,即(*p1)++;<==>a++;
*p1++;//先得到*p1的内容,*p1++;<==>*(p1++);
3.&*p等价于p
*&a等价于a
eg1:
#include
main()
{
inta=5,b=3;
int*p;
p=&a;
b=*p+5;
printf("%d\n",b);//b=10;
*p=4;
printf("%d,%d\n",a,*p);//a=4;*p=4;
}
eg2:
同指针变量来交换两个单元中的内容。
#include
main()
{
inta,b,c,*p1=&a,*p2=&b;
scanf("%d%d",p1,p2);
c=*p1;*p1=*p2;*p2=c;
printf("a=%d,b=%d\n",*p1,*p2);
}
2.运算规则
*、&:
优先级相同,且右结合
与++、--、!
等单目运算符的优先级相同
高于算术运算符*、/、%
eg1:
#include
main()
{
inta=2,*p=&a,*q=&a;//*p=&a--〉已定义的变量的地址为指针变量赋值
printf("*p++=%d,*(q++)=%d\n",*p++,*(q++));
//*p++=2,*(q++)=2
//*p++,先运算*p,再p++。
*p在左边,为取内容
//*(q++),地址相加(q++=(&a)++)而不是a++。
先运算q,再q++
//指针变量里的值相加,使指针指向了其他的变量
p=&a;
q=&a;
printf("*p=%d,(*q)++=%d\n",*p,(*q)++);
//*p=3,(*q)++=2;
//(*q)++,所指向的变量的值相加,即a++
}
eg2:
写出下面各表达式的结果,并找出具有等价关系的对子。
eg:
inta=5,*p=&a;//*p=&a:
已定义的变量的地址为指针变量赋值*p指向a-->*p=a
&*p=&a;//p=&a;*p=a;&*p=&a=p;
*&a=a;//p=&a;*p=a;*&a=*p=a;
(*p)++=a++;
*p++=*(p++);//*(p++)=*((&a)++)
eg1:
#include
main()
{
inta,b,c;
int*pa,*pb,*pc;
pa=&a,pb=&b,pc=&c;
scanf("%d%d",pa,pb);//*pa=3,*pb=4
//scanf("%d%d",&a,&b);
printf("&a=%d,&b=%d\n",pa,pb);//地址&a=2293408,&b=2293404
printf("a=%d,b=%d\n",*pa,*pb);//数据a=3,b=4
c=a+b;printf("c=%d\n",*pc);//a=3,b=4,c=3+4=7
*pc=a+*pb;printf("c=%d\n",c);//a=3,b=4,c=3+4=7
c=*pa**pb;printf("c=%d\n",c);//a=3,b=4,c=3*4=12
c=++*pa+(*pb)++;printf("c=%d\n",c);//a=4,b=4,c=4+4=8,b=5
c=(*pa)+++*pb;printf("c=%d\n",c);//a=4,b=5,c=4+5=9,a=5
printf("a=%d,b=%d\n",a,b);//a=5,b=5
}
eg2:
交换两个数a、b的值。
#include
main()
{
//inta=5,b=8;
//intt;
//printf("a=%d,b=%d\n",a,b);
//
//t=a;
//a=b;
//b=t;
//printf("a=%d,b=%d\n",a,b);
inta=5,b=8;
int*pa=&a,*pb=&b;//已定义的变量的地址(&a/&b)为指针变量(*pa/*pb)赋值
intt;
printf("a=%d,b=%d\n",a,b);
t=*pa;//*pa:
pa所指向的单元的内容--〉a
*pa=*pb;
*pb=t;
printf("a=%d,b=%d\n",a,b);
}
4.指针变量作函数参数
eg1:
编写一个函数实现两个数的交换。
////×子函数交换,主函数未交换。
//#include
//voidswap(intx,inty)内容单元名存储单元(假设位置)
//{3a2A02
//intt;//局部变量5b2C16
//t=x;x=y;y=t;//子函数交换变量拷贝赋值
//}3x(a)4012
//main()5y(b)4016
//{值交换后-->存储单元不一样,未完成交换
//inta=3,b=5;5x4012
//swap(a,b);3y4016
//printf("%d%d\n",a,b);//主函数未交换
//}
√指针变量间接访问
#include
voidswap(int*x,int*y)//使用指针变量存储单元
{内容单元名存储单元(假设)
intt;3a2A02
t=*x;*x=*y;*y=t;//地址交换5b2C16
//t=*x;-->*x所指向的单元内容赋值给t。
地址赋值
}2A02x(&a)4012
main()2C16y(&b)4016
{内容交换后
inta=3,b=5;5*x(a)2A02
swap(&a,&b);//地址值3*y(b)2C16
//实参传递地址值,形参一定是指针变量
printf("%d%d\n",a,b);
}
////×地址交换,内容没变。
//#include
//voidswap(int*x,int*y)//定义指针变量存储单元
//{内容单元名存储单元(假设)
//int*t;//定义局部指针变量3a2A02[2C16]
//t=x;x=y;y=t;//地址交换5b2C16[2A02]
//}地址赋值↑
//main()2A02x(&a)4012↑
//{2C16y(&b)4016↑
//inta=3,b=5;地址交换后-->a和b的地址交换了,内容不变。
//swap(&a,&b);//地址值2C16x(&a)4012
//printf("%d%d\n",a,b);2A02y(&a)4016
//}
////×危险错误:
*t中地址不确定,不可存放内容。
//#include
//voidswap(int*x,int*y)//定义指针变量
//{
//int*t;//定义局部指针变量
////intw;t=&w;//给*t指定地址,则程序正确。
//*t=*x;*x=*y;*y=*t;
////*t中地址(t)随机,则*t所指向的单元内容存放位置不得当。
//}
//main()
//{
//inta=3,b=5;
//swap(&a,&b);//地址值
//printf("%d%d\n",a,b);
//}
eg2:
输入a,b,c三个数,按大小顺序输出。
-->四个数排序输出,需要6次两两比较交换。
#include
voidswap(int*x,int*y)//定义指针变量
{
intt;//定义局部指针变量
t=*x;*x=*y;*y=t;
}
main()
{
inta,b,c;
printf("enterdataa,b,c:
");
scanf("%d%d%d",&a,&b,&c);
if(a
if(a if(b printf("%d%d%d\n",a,b,c); } 指针和数组 1.一维数组与指针 1.数组是连续存放的若干个元素的集合。 2.数组名就是指向此数组第1个元素的指针(首地址) eg: inta[10],*p=a;则p=a;等价于p=&a[0]; 3.某一元素的地址: p=&a[i]; 用指针引用该元素: *p=a[i];//a[i]: a数组中下标为i的元素 4.数组元素的下标在内部实现时,统一按“基地址+位移”的方式处理。 a: a数组中的首地址=&a[0]; a+1: a数组中下标为1的元素地址=&a[1]; a+i: a数组中下标为i的元素地址=&a[i]; 位移eg: a数组是int整型,占用两个字节。 假设a数组首地址a=3A00; 则a[1]=a+1*2=3A02; a[i]=a+i*2; 故表示数组元素的地址可以用: &a[i]、p+i、a+i(p=a) 表示数组元素的内容可以用: 下标表示法a[i] 指针表示法*(p+i)、*(a+i) 5.数组名a(数组的指针)与指向数组首地址的指针变量p性质不同。 (a不是变量,它是一个常量,不会改变值。 ) eg1: #include main() { inta=3,b=5; int*p=&a;//p=&a; printf("*p=%d\n",*p);//*p=3 *p=4;//a=*p; p=&b; printf("*p=%d\n",*p);//*p=5 *p=6;//b=*p; printf("a=%d,b=%d\n",a,b);//a=4,b=6 } eg2: 1.#include main() { inti,a[5]; int*p; for(i=0;i<5;i++) { p=&a[i];x a[i]=i;//*p=a[i]=i; printf("a[%d]=*p=%3d\n",i,*p); } printf("\n"); } /* a[0]=*p=0 a[1]=*p=1 a[2]=*p=2 a[3]=*p=3 a[4]=*p=4 -------------------------------- */ 2.#include main() { inti,a[5]; int*p=a;//p=a;或p=&a[0]; //i++;指i单元的内容+1 //p++;指地址移到下一个元素(下一个元素的长度与数据的类型有关系) for(i=0;i<5;i++,p++) { *p=i;//a[i]=i; printf("a[%d]=*p=%3d\n",i,*p); } printf("\n"); } /* a[0]=*p=0 a[1]=*p=1 a[2]=*p=2 a[3]=*p=3 a[4]=*p=4 -------------------------------- */ 6.数组指针(a)、指针变量(p)与数组元素(a[i])之间的关系: 设有inta[10],*p=a;则 地址关系 指针变量p数组指针a数组元素 pa&a[0] p+1a+1&a[1] p+2a+2&a[2] ... p+ia+i&a[i] ... p+9a+9&a[9] 内容关系 指针变量p数组指针a数组元素 *p*aa[0] *(p+1)*(a+1)a[1] *(p+2)*(a+2)a[2] ... *(p+i)*(a+i)a[i] ... *(p+9)*(a+9)a[9] eg: 数组的使用形式 #include main() { inti,a[5],*p=a; printf("input5numbers: \n"); for(i=0;i<5;i++) //scanf("%d",&a[i]);//数组的使用形式 //scanf("%d",a+i); scanf("%d",p+i); printf("outputthesenumbers: \n"); for(i=0;i<5;i++)printf("%d",a[i]);//a[i]可换为*(a+i)或*(p+i) printf("\n"); } 2.指针的运算(指向数字的指针p的运算) 1.赋值运算-->指针类型相同。 eg: p=&x;//将x的地址赋给p p=a;//将a数组的首地址赋给p p=NULL; 2.加减运算-->只能用于数组元素的引用,注意下标的有效范围。 即加减运算必须在连续空间上的加减(移动)才有意义。 用法: 指针+/-整数 eg: a+i-->a是一个数组名,表示地址的首地址,只能加不能减。 p+/-i-->p是一个指针变量,指向某一个数组元素,可进行加减。 p-q;//p和q都是指向同一个连续存储的空间(相减得到相隔两个元素的个数) 3.两指针的相减运算: 求两地址的间距-->两个指针的类型相同,并指向同一连续的存储区域。 用法: 指针-指针 eg: p-a-->a为数组首地址保持不变,p可以移动(求这个地址到首地址跟了几个元素) 4.移动指针(++、--)-->对数组名(常量)/简单变量不能实施该运算。 eg: p++;//后移p=p+1;要求p为变量(指针变量),不能是常量(数组名)。 p--;//前移 5.比较运算(p和q都是指向同一个连续存储的空间) 比较两个元素相隔的个数 用法: 指针运算符指针 eg: p 地址 比较: 字符量根据ascii码; 数值量根据数值大小; 指针变量根据地址大小 2~5运算通常用于指向数组的指针[连续空间的指针] eg: 将数组a的数据复制到数组b中并输出出来。 //数组下标的方法 #include #defineM7 main() { inti,a[M]={23,15,50,3,21,20,35}; intb[M]; for(i=0;i printf("outputthesenumbers: \n"); for(i=0;i printf("\n"); } //指针的方法 #include #defineM7 main() { inti,a[M]={23,15,50,3,21,20,35}; intb[M]; //p指向a的首地址&a[0];q指向b的首地址&b[0] int*p=a,*q=b; for(i=0;i { //*q=*p;//将p地址所指向的内容赋给q地址 //q++;//地址指针+1 //p++; //将p地址所指向的内容赋给q地址,然后p、q后移 *q++=*p++; } printf("outputthesenumbers: \n"); //for(i=0;i q=b;//将q指针重新指向b数组的首地址 for(i=0;i printf("\n"); } 3.数组的指针与函数参数 数组作为函数参数,实参和形参的对应关系可归纳以下四种情况: ①形参是数组x[];实参是数组名a intf(intx[],intn) {} main() { inta[10]; ... f(a,10); ... } ②形参是指针变量*x;实参是数组名a---常用形式 intf(int*x,intn) {} main() { inta[10]; ... f(a,10); ... } ③形参是指针变量*x;实参是指针变量p,指向数组a的首地址---常用形式 传进去地址,也用指针接收 intf(int*x,intn)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 笔记 指针
![提示](https://static.bdocx.com/images/bang_tan.gif)