




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计
第8章指针生活中的编号地址和指针的基本概念●●●0124G-1地址——编号一个字节34G内存
4×1024×1024×1024个字节1000100110021003a2000200120022003binta=1;doubleb=8.2;a:1
b:
8.2
有了变量的地址,存取变量就可以通过两种方式:实际地址:2031132、3209356
(十六进制:0x001efe1c、0x0030f88c)1)通过变量名2)通过变量的地址数学系男生宿舍,也可以说是305宿舍。10002000变量a占据编号1000~1003的4个字节——变量a的地址为1000
变量b占据编号2000~2007的8个字节——变量b的地址为2000
8.220042005200620071地址和指针的基本概念1000,2000
1,8.2
变量的值(内容)变量的地址区别地址不变内容可变●●●0124G-1一个字节31000100110021003a2000200120022003b8.2200420052006200714G内存
4×1024×1024×1024个字节地址——编号a:1
b:
8.210002000有了变量的地址,存取变量就可以通过两种方式:1)通过变量名2)通过变量的地址inta=1;doubleb=8.2;数学系男生宿舍,也可以说是305宿舍。inta=1;doubleb=8.2;a:1
b:8.2
10002000保存指针变量特殊的专用变量int*p;p=&a;p:
[]
*是标志:定义的是指针变量, 不是普通变量;变量名叫p,不是叫*p。变量的类型是int*,不是int
指针变量一律占4字节
指针变量简称指针
1000
3000只能保存数据不能保存地址Hi,这是指针变量,存地址的!不是存数据的普通变量哦!只能保存地址不能保存数据●●●3000300130023003p[1000]4G-14G内存
4×1024×1024×1024个字节01231000100110021003a2000200120022003b8.220042005200620071定义指针变量2000200120022003b8.22004200520062007p=&a;double*q;inta=1;doubleb=8.2;int*p;a:1
b:
8.2
10002000p:
[]3000指针变量的基类型指针变量p指向了变量a
p是指向变量a的指针变量
p是指向变量a的指针
基类型基类型:指针变量所指向的变量的类型
p=&b;q:[]4000p不是int型而是int*型q=&a;q=&b;
2000
●●●4000400140024003q[2000]q不是double型,更不是int型而是double*型4G内存
4×1024×1024×1024个字节3000300130023003p[1000]2000200120022003b8.220042005200620074G-11000
p:
[]a:1
b:
8.2
100020003000q:[]4000
2000
指针变量基类型里的“大小王”基类型void*void*r;r:[]5000r是void*型r=&a;r=&b;
1000
[2000]
●●●void类型的指针变量4000400140024003q[2000]3000300130023003p[1000]2000200120022003b8.220042005200620075000500150025003r4G内存
4×1024×1024×1024个字节4G-1inta=1;doubleb=8.2;int*p;p=&b;double*q;q=&a;q=&b;p=&a;1000
[1000][2000]指针变量的赋值为指针变量赋值,有三种方法①赋值语句的方法p=&a;intb=2;int*q;p:[]int*p;inta=1;a:1
10002000指针变量被赋值前,其值为随机数——随机地址。若此时访问或修改它所指向的空间的内容,会造成意外后果,甚至导致系统崩溃!变量名叫p不是叫*p
1000
*p=&a;4000q:[]③允许指针变量之间赋值,但两个指针变量必须基类型相同q=p;int*r;r=q;double*s;s=p;b:
2
3000?
账户密码?Windows系统重要空间?其它程序变量?②定义指针变量时初始化(定义时赋初值)intb=2;int*q=&b;[1000]r:[?]5000[1000]s:[?]6000s占4字节
3000
指针变量的赋值(2)不允许把一个“数”当地址赋给指针变量
int*p; p=1000;p:[]2000a:1
1000特殊地,允许:
p=0;或p=NULL;指针变量值为0(地址值为0)时,表示什么也不指向——空指针01230
?地址为0开始的一段内存非常重要!p:[?]2000p:[0]2000指针变量未赋值:指向随机(不确定)指针变量值为0(确定):不指向任何内容v.s(必须用&
取变量的地址,如p=&a;)NULL(必须全部大写)是系统定义的宏#define
NULL0指针运算两兄弟——两个运算符(2)*
指针运算符(间接访问运算符)
——获取或改写以p为地址的内存的内容: *p*
不是获得或改写指针变量本身的值,而是获得或改写它所指向单元的值。&是运算符*是运算符(1)&
取地址运算符
——获取变量的地址
&变量名
&可用于普通变量,也可用于指针变量,后者取指针变量本身的地址。都不是变量名的一部分!我是*快递员从哪取货,或您要送哪?地址给我,马上办到!*
运算只能用于指针变量,不能用于普通变量(如*a错误)。int
*p;与定义指针变量时的*不同:*相同符号不同含义&
和*
互为逆运算:如果p=&a;p
&a*p
*&a
a&*p
p&*&*&*p
p*&*&*&*p
ainta=1,b=2;int*p=&a;*p=&a;*p=b;p=a;p=&b;*p=3;练习3000p:[1000]a:
11000b:
22000不是说*p=&a而是p=&a变量类型是int*
不是
int[2000]p指此处,此处只能存地址,不能存数据。故p=a;错误23double*px,*py=0,x=0,y;*px=0;px=0;y=py;px:[?]4000py:[0]5000x:
0.0
6000y:
?
7000[0]不是*py=0,还是py=0为p赋值,这里叫p不叫*p此处只能存数据,不能存地址未知空间被意外修改*p是指此处此处只能存数据,不能存地址故*p=&a;错误总结C语言中的*我是*快递员从哪取货,或您要送哪?地址给我,马上办到!①定义指针变量,*是一个标志,无运算的含义,如:
int
*p;②取地址指向的内容,或改写指向的内容,*是指针运算符,如*p③算术表达式中*是乘法运算符,如:a*b④指针变量做函数形参、函数返回值类型同①
,如:int*fun(int
*p,int
*q){…}有int等类型说明符*
后有一个地址量,*前无内容*
前后各有一个量Hi,这是指针变量,存地址的!不是存数据的普通变量哦!位于函数的形参表中;位于函数返回值类型后*相同符号不同含义总结C语言中的指针变量指针变量保存地址的专用变量。
定义时必须有*,如int*p;使用时有*、无*的情况均有*p
表示取地址指向的内容或改写内容
p
表示p中保存的地址本身
a:1
1000p:[1000]2000&p
表示变量p的地址有int等类型说明符即为定义
无int等类型说明符即为使用
程序例输入a和b两个整数,按先大后小的顺序输出a和b。#include<stdio.h>main(){
int*p1,*p2,*p,a,b; p1=&a;p2=&b; scanf("%d%d",&a,&b);
if(a<b) printf("\na=%d,b=%d\n", a,b); printf("max=%d,min=%d\n", *p1,*p2);}p1:[]3000p2:[]4000b:
2000a:
1000p:[
]5000_
2030
2030a=20,b=302030a=20,b=30max=30,min=20并未交换a、b本身,而是交换了指向,使p1指向较大数[2000]
1000
2000
20301000
[1000]
{p=p1;p1=p2;p2=p;}{p=p1;p1=p2;p2=p;}数组的指针指向一维数组元素的指针a:a[0]a[1]a[2]a[3]a[4]12345inta[5]={1,2,3,4,5};int*p;p=&a[1];p=&a[0];10001004100810121016p:[?]2000float*q;q=&a[1];[1004][1000]q:[?]3000q只能保存float型变量的地址,而a[1]为int型(设在VisualC++2010中)10001004100810121016指针变量的运算——加减整数a:a[0]a[1]a[2]a[3]a[4]12345p:[?]2000[1004][1000]p=p+1;
[1004]p+=2;
p--;
指向向前或向后移动n个单位(n个元素)p±n=p中的地址编号±(每元素字节数×n)指针变量加上或减去一个整数n:[1012][1008]+1下一站(该运算应只对指向数组的指针变量进行,否则毫无意义)京沪高铁(设在VisualC++2010中)inta[5]={1,2,3,4,5};int*p;p=&a[1];p=&a[0];指针变量的运算——加减整数(2)每个char型变量占1字节,对基类型为char的指针变量±n,恰好是地址±n
c:c[0]c[1]c[2]c[3]'a''b''c''d'charc[4]={'a','b','c','d'};char*p=&c[2];p:[1002]20001000100110021003[1003]++p;
p-=2;
[1001]void类型的指针不能做±n的运算(也不能做++、--的运算)指针变量的运算——指针变量相减两指针变量的加法、乘法、除法运算是没有意义的。例如,p1+p2、p1*p2、p1/p2均无意义。结果为两地址间相差的单位个数(元素个数),不一定是相差的字节数:
p1-p2=(p1中的地址编号-p2中的地址编号)/每元素字节数两指针变量相减:(该运算应只在指向同一数组的元素的两个指针变量之间进行)x:x[0]x[1]x[2]x[3]x[4]x[5]doublex[6];double*p1=&x[1],*p2=&x[5];printf("%d",p2-p1);p1:[1008]2000p2:[1040]30001000100810161024103241040=(1040-1008)/8京沪高铁相差4站指针变量的运算——关系运算p1==p2 表示p1和p2指向数组的同一元素;
p1>p2 表示p1所指元素位于p2所指元素之后;
p1<p2 表示p1所指元素位于p2所指元素之前。两指针变量之间可以进行大小的比较,即是比较两指针变量中所保存的地址编号的大小。两指针变量间的关系运算:(该运算一般只对指向同一数组的元素的两个指针变量进行,表示它们所指元素的先后位置)p==0或p==NULL
表示p是空指针,不指向任何位置;p!=0或p!=NULL表示p不是空指针。指针变量还可以与0比较:逆置数组元素逆置数组a中7个元素的值。数组a中7个元素的原始排列为1、2、3、4、5、6、7,逆置后使其排列为7、6、5、4、3、2、1。a:a[0]a[1]a[2]a[3]a[4]a[5]a[6]123456710001004100810121016(设在VisualC++2010中)10201024#include<stdio.h>#define
N7main(){ inta[N]={1,2,3,4,5,6,7},i,t;
int*p=&a[0],*q=&a[N-1];
while(p<q) { t=*p;*p=*q;*q=t; p++;q--; }
for(i=0;i<N;i++)//输出结果
printf("%d",a[i]); printf("\n");}p:[1000]2000q:[1024]300071p++;q--;[1004][1020]62[1008][1016]53[1012]7654321
数组元素的地址转换为元素下标a:a[0]a[1]a[2]a[3]a[4]12345inta[5]={1,2,3,4,5};int*p,*q;q=&a[0];//0号元素地址
p=&a[2];10001004100810121016p:[1008]2000q:[1000
]3000(设在VisualC++2010中)设指针变量p指向了数组a的某个元素(保存了某个元素的地址),如何通过指针变量p,得到它所指元素的下标呢?p-数组0号元素的地址p-数组名
(数组名就是0号元素的地址)
p-q则得2,即p所指元素a[2]的下标p-a则得2,即p所指元素a[2]的下标一维数组的指针a:a[0]a[1]a[2]a[3]a[4]1234510001004100810121016inta[5]={1,2,3,4,5};
一维数组名a
①是数组名(一维数组)②是一个假想的指针变量③a值为数组起始地址,也是元素a[0]的地址④指针变量a本身的地址(a所在“内存”位置)也是数组的起始地址,也是元素a[0]的地址⑤a值不可被改变,是常量
a:[1000]1000两个重要公式——语法糖a:a[0]a[1]a[2]a[3]a[4]1234510001004100810121016a+0&a[0][1000]
a+1&a[1][1004]
a+2&a[2][1008]
a+i&a[i]*(a+i)*&a[i]a[i]*(a+i)a[i]编译时编译系统将a[i]全部变为*(a+i)。a[i]这种写法只不过是C语言为便于我们理解而特意设计的——语法糖我只认得*(a+i),不知道a[i]是什么东东!
a[2]a[0]a[4]a[3]a[1]语法糖a:[1000]1000inta[5]={1,2,3,4,5};两个重要公式(2)x为数组名、或指针变量,均适用(但对普通变量不适用)C语言规定:指针变量也可写为数组的形式如有int
*p;可写为:p[0]p[1]p[2]当x是数组名时,x本身也是指针变量(假想的),因此无论x是数组名还是指针变量实际是。*(p+i)p[i]p+i&p[i]*(a+i)a[i]a+i&a[i]*(x+i)x[i]x+i&x[i]一回事指针变量与一维数组名的统一inta[5];p=&a[0];inta[5];int*p;p=a;p:[1000]2000p[0]*(p+0)
*[1000]
a[0]*p
p[1]*(p+1)
*[1004]
a[1]p[i]a[i]*(p+i)*(a+i)pap的值(地址)可被修改,a的值(地址)不能被修改p是变量,a是假想的“指针变量”(是常量)p=&a[1];p++;p=0;p=NULL;p=a;a=&a[1];a++;a=0;a=NULL;a=p;a:a[0]a[1]a[2]a[3]a[4]1234510001004100810121016a:[1000]1000指针变量与一维数组名的统一数组名指针变量指针变量与数组名互换使用的前提①指针变量保存数组起始地址;②数组名(假想的指针变量)不能被修改值数组首地址&a[0]ap数组元素
a[i]p[i]*(a+i)*(p+i)指针访问效率更高inta[5];p=&a[0];inta[5];int*p;p=a;p:[1000]2000a:a[0]a[1]a[2]a[3]a[4]1234510001004100810121016a:[1000]1000练习(1)设有定义doublea[10],*s=a;以下能够代表数组元素a[3]的是A)(*s)[3]B)*(s+3)C)*s[3]D)*s+3a:a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]a:[1000]100010001008101610241072s:[1000]200011[3]s[3]a[3]sa(注意a的值不可被改变)*a[3]4*41+3
*[1024]方法2练习(2)设有定义doublea[10],*s=&a[2];能够代表数组元素a[3]的是___________a:a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]a:[1000]100010001008101610241072s:[1016]2000sa(s不是a的起始地址)*(s+1)
或s[1]
s+1:[1024]*(s+3)
或s[3]
代表的是a[5]s+3:[1040]10321040*(x+i)x[i]x+i&x[i]以不变应万变x为指针变量或数组名s[]与a[]的下标差2语法糖公式永远成立求字节运算符sizeof(类型或表达式)求占用多少字节
(结果为整数)sizeof是关键字是运算符,不是函数!sizeof用于数组名sizeof(指针变量):得4sizeof(数组名):获得数组所有元素共占字节数#include<stdio.h>intmain(){
inta[5]={1,2,3},i; //最后2个元素自动补初值0
int*p=a;
intlen=sizeof(a)/sizeof(int);
//len=5,即数组元素个数
printf("%d",len);
//输出5
printf("%d\n",sizeof(p));
//输出4
//依次输出数组每元素值
for(i=0;i<len;i++)
//i<len即i<5
printf("%d",a[i]);
return0;}54123002044指针运算的优先级#include<stdio.h>main(){ inta[]={1,3,5},*p=a+1; printf("%d,",*p++); printf("%d\n",(*p)++);}a:a[0]a[1]a[2]135100010041008p:[1004]2000a:[1000]1000*、&
的优先级与++、--相同,都非常高,仅次于()与++、--同级运算时,从右至左结合3,[1008]*(p++)a[2]++3,5
6[1004]二维数组的指针**[[写字台抽屉]]
“二级”指针变量a:11000p:
[1000]2000q:
[[2000]]3000软件学院B310
上课地点在: 软件学院B310上课地点的地址在: 写字台抽屉
上课地点在: 软件学院B310
地址的地址地址一级指针变量二级指针变量指针变量 *[[写字台抽屉]]
[软件学院B310]
*[软件学院B310]
上课教室
*q
p**q
*pa**[[2000]]
*[1000]1*[[2000]]
[1000]二维数组的地址intb[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
123456789101112[1000]1[1004]2[1008]3[1012]4[1016]5[1020]6[1024]7[1028]8[1032]9[1036]10[1040]11[1044]121000b[0][1000]1[1004]2[1008]3[1012]4b[1][1016]5[1020]6[1024]7[1028]8b[2][1032]9[1036]10[1040]11[1044]12三个一维数组b[0]:[1000]1000b[1]:[1016]1016b[2]:[1032]1032int*p;b:[[1000]]1000一级指针变量二级指针变量p:[5000]2000①是数组名(二维数组)②是一个假想的二级指针变量③b值为数组第0行的地址(一维数组b[0]的地址),数值上与b[0][0]的地址相等,但它是二级的④指针变量b本身的地址(b所在“内存”位置)数值上也与b[0][0]的地址相等,但它是三级的⑤b值不可被改变,是常量
二维数组名b
二维数组的地址(2)b[0]:
[1000]1000b[2]:
[1032]1032b[0][1000]1[1004]2[1008]3[1012]4b[1][1016]5[1020]6[1024]7[1028]8b[2][1032]
9[1036]10[1040]11[1044]12b[1]:
1016[1016]一级“指针变量”(假想的)
二级“指针变量”(假想的)
零级具体数据级别不同int*p;p=b;级别相同才能彼此赋值
p=b[0];p=b[1];p=b[2];inta[5];
p=a;p:[]2000
1000
[1016][1032]b:
[[
1000
]]1000b[0]:
[1000]1000b[2]:
[1032]1032b[1]:
1016[1016]行指针行指针特殊的专用变量保存int(*q)[4];*、()、[4]三者都不可少
q=b;
q=b[0];q=b[1];q=b[0][0];b[0][1000]1[1004]2[1008]3[1012]4b[1][1016]5[1020]6[1024]7[1028]8b[2][1032]
9[1036]10[1040]11[1044]12Hi,这是指针变量,存地址的!不是存数据的普通变量哦!定义形式够复杂了!但表示的意义很简单——定义一个二级指针变量q
[[]]q:20001000b:
[[
1000
]]1000行指针±整数q++;指向第0行指向第1行指向第2行q++;b++;b++;b是假想的指针变量,值不能改b[0]:
[1000]1000b[2]:
[1032]1032b[1]:
1016[1016]b[0][1000]1[1004]2[1008]3[1012]4b[1][1016]5[1020]6[1024]7[1028]8b[2][1032]
9[1036]10[1040]11[1044]12[[]]q:20001000
[[1016]][[1032]]
int
b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int(*q)[4];q=b;b:
[[
1000
]]1000行指针±整数,或二维数组的数组名±整数:移动一行指针变量±整数后,“级别”不变。两个重要公式(语法糖)同样适用对二级指针变量q或二维数组名b两个重要公式同样适用b[i]
*(b+i)
b[i][j]
*(b[i]+j)
*(*(b+i)+j)
特殊地,i=0、j=0时,b[0][0]
**b&b[0][0]
*b行指针与二维数组名可互换使用。二维数组元素的写法
原来是的b[i][j]
*(*(b+i)+j)
语法糖q[i]
*(q+i)
q[i][j]
*(q[i]+j)
*(*(q+i)+j)
*(q+i)q[i]q+i&q[i]*(b+i)b[i]b+i&b[i]*(x+i)x[i]x+i&x[i]指针变量与一维数组名的统一a:
[3000]3000行指针和二维数组名的统一b:[[1000]]1000q:[[]]2000
1000a:a[4]a[3]a[2]a[1]a[0]3000
inta[5];
int*p;p=a;p:
[3000]4000p[i]a[i]p的值能改;a的值不能改p
a
intb[3][4];
int(*q)[4];q=b;0123012b:1000
q的值能改;b的值不能改q
b
q[i]b[i]q[i][j]b[i][j][[1016]]b[1]:[1016]1016
q[0][0] b[0][0]q[1] b[1]q=b; b=q;q=&b[1]; b=&b[1];q++; b++; q=0;或q=NULL; b=0;或b=NULL;b的值不能被改所有的错误同样原因:[[1032]][[0]]一个表格、两句法则草稿写法±1效果定义二级指针
移动一行int(*q)[4];intb[3][4];中的b
必移动4字节int**r;int*s[3];中的s一级指针
移动一个单位(int型4字节,char型1字节…)int*p;inta[2];中的a普通变量
变量值±1intx;法则:①定义变量时:一个*或一个[]
升一级 ②使用时:一个*或一个[]降一级;一个&升一级[[]][[]][]q与b统一p与a统一r与s统一看做不同级别,不能互相赋值行指针和指针赋值小结intx[3][10];int(*p)[4];p=x;一行4个元素!int(*q)[10];q=x;一行10个元素!double(*r)[10];r=x;基类型不同p:[[]]20000123456789012q:[[]]3000r:[[]]4000int*s;s=x;x:[[1000]]1000x[0]:[1000]1000级不同s=x[0];s:[]50001000
1000
x=q;x不能改x[0]=s;x:1000
x[0]不能改两个指针变量间的赋值必须同时满足:①级别相同(二级指针变量分两类,两类之间还是不同级);②对行指针和二维数组,每行的元素个数相同;③两个指针变量的基类型相同;④数组名不能被赋值,其值不能被改变。A)p=s; B)p=k;C)p=s[0];D)s[0]=p;E)k=s;F)s=k;G)p=&s[1][2];H)k=&s[1][2];练习若有定义语句:chars[3][10], *p;以下赋值语句正确的是级不同二级二级一级级不同s[0]是假想的指针变量,是s的第0行这个一维数组的首地址,将之 赋值给p[1000]一行几个元素不同s是假想的二级指针变量,其值不能改s[0]的值不能改元素s[1][2]的地址 赋值给p级不同s是假想的指针变量,将其值(数组首地址) 赋值给k[[1000]][1012]法则: ①定义变量时:一个*或一个[]
升一级 ②使用时:一个*或一个[]降一级;一个&升一级(*k)[3],(*k)[10],
指针数组一个数组,各元素都是指针变量,都保存地址。指针数组所有元素基类型相同,即都要指向相同数据类型的变量。int*s[3];s:s[0]s[1]s[2][][][]inta[3];a:a[0]a[1]a[2]int(*q)[3];q:[[]]每元素的基类型元素个数Hi,这是指针变量的数组,不是普通数组,每个元素都是存地址的!或写为:int*(s[3]);每元素都是指针变量,都必占4字节无论基类型如何若double*s[3];s[0]、s[1]、s[2]也都占4字节100010041008区分指针数组inta,b,c;a:b:
c:200030004000s[0]=&a;s[1]=&b;s[2]=&c;
一个数组,各元素都是指针变量,都保存地址。指针数组所有元素基类型相同,即都要指向相同数据类型的变量。int*s[3];s:s[0]s[1]s[2][][][]100010041008[4000][3000][2000]s[2]s[1]s[0]指针数组的地址指针数组*(s+i)s[i]s+i&s[i]
公式同样适用:语法糖int*s[3];s[0]s[1]s[2][][][]100010041008s:[[1000]]1000s:①是数组名(指针数组)②是一个假想的二级指针变量 与“二维数组名”的“二级”不同!
③s值为指针数组的起始地址,也即元素s[0]的地址,它是二级的④指针变量s本身的地址(s所在“内存”位置)数值上与s[0]的地址相等,但它是三级的⑤s值不可被改变,是常量
指针数组名p
指针的指针指针数组s:[[1000]]1000一级指针变量保存行指针±1移动一行,这里没有“行”保存行指针级不同int*s[3];s:s[0]s[1]s[2][][][]100010041008s:[[1000]]1000指针的指针与指针数组名的统一指针数组int*s[3];特殊的专用变量指针的指针int**r;r:[[]]2000Hi,这是指针变量,存地址的!**表示二级指针变量!r=s;1000
指针数组名指针的指针r[i]s[i]*(r+i)*(s+i)s:s[0]s[1]s[2][][][]100010041008保存r:[[]]20001000
指针数组名/指针的指针±整数指针数组r++;r++;s++;s++;s是假想的指针变量,值不能改
[[1004]]指向指针变量s[0]指向指针变量s[1]指向指针变量s[2]s:s[0]s[1]s[2][][][]s:[[1000]]1000100010041008int*s[3];int**r;r=s;指针的指针[[1008]]
每个指针变量必占4字节,无论指针变量的基类型。±1必移动4字节指针三家人——一个表格、两句法则草稿写法±1效果定义二级指针
移动一行int(*q)[4];intb[3][4];中的b
必移动4字节int**r;int*s[3];中的s一级指针
移动一个单位(int型4字节,char型1字节…)int*p;inta[2];中的a普通变量
变量值±1intx;法则:①定义变量时:一个*或一个[]
升一级 ②使用时:一个*或一个[]降一级;一个&升一级[[]][[]][]q与b统一p与a统一r与s统一看做不同级,不能互相赋值练习1)若有定义inta[4][10],*p,*q[4];且0<=i且i<4,则错误的赋值语句是A)p=a; B)q[i]=a[i]; C)p=a[i]; D)p=&a[2][1];E)q=a; F)p=q;2)有定义语句:int*p[4];以下选项中与此语句等价的是A)intp[4]; B)int**p;C)int*(p[4]); D)int(*p)[4];二级二级一级①定义变量时:一个*或一个[]
升一级②使用时:一个*或一个[]降一级;一个&升一级级不同二级分两种级不同级不同3)若有定义int(*pt)[3];则下列说法正确的是A)定义了基类型为int的三个指针变量B)定义了基类型为int的具有三个元素的指针数组ptC)定义了一个名为*pt、具有三个元素的整型数组D)定义了一个名为pt的指针变量,它可以指向每行有3个整数元素的二维数组的一行使用指针的指针访问普通变量#include<stdio.h>intmain(){ inta,*p,**q; a=1; p=&a; q=&p; printf("q=%d\n",q); printf("p=%d\n",p); printf("%d\n",*q); printf("%d\n",**q); printf("%d\n",*p); **q=5; printf("%d\n",**q); printf("%d\n",a); return0;}a:11000p:
[1000]2000q:
[[2000]]3000q=2000p=1000int(*q)[4];q=&p;int*q;q=&p;级不同级不同(二级分两类)q=2000p=10001000q=2000p=1000100011q=2000p=100010001155q=0x0013FF78p=0x0013FF7C0x0013FF7C11555指针总结表格及指针阅读法草稿写法±1效果定义二级指针
移动一行int(*q)[4];intb[3][4];中的b
必移动4字节int**r;int*s[3];中的s一级指针
移动一个单位(int型4字节,char型1字节…)int*p;inta[2];中的a普通变量
变量值+1intx;[[]][[]][]q与b统一p与a统一r与s统一函数指针:
int(*pf)(参数,参数,…);定义形式逆序阅读
先读变量名/函数名,后接“是...”* 读作“指针,指向……”[] 读作“数组,每元素是...”[]内为元素个数() 读作“函数,返回值是...”()内为它的参数int
以最后的语义为准
(对变量或数组类型为int,对指针为指向int,对函数为返回int)优先级[]与()一致,均比*高q是指针,指向数组(被指数组有4个元素(每行)),被指数组每元素是int
b是数组(数组有3个元素),每元素又是数组(是包含4个元素的数组),后者数组每元素是int
r是指针,指向指针,后者指向int
s是数组(数组有3个元素),每元素是指针,都指向int
p是指针,指向int
a是数组(数组有2个元素),每元素是int
pf是指针,指向函数
(参数是后面的样子),返回值是int
x是int指针函数参数指针变量作函数参数输入两个整数按大小顺序输出。今用函数处理且用指针作参数。小明和小红下课后互相拿错作业本了,请去宿舍找他们,帮他们把作业本换一下吧。他们的宿舍都在哪啊?他们的宿舍分别是309和312。没问题,我去找他们!单向传递实参(地址)形参temp=*[309]; //去309取小明的作业本拿到手中*[309]=*[312]; //去312取作业本送到309的小明
*[312]=temp; //将手中小明的作业本送到312的小红main的空间指针变量作函数参数——程序1#include<stdio.h>intmain(){ inta,b,*p1=&a,*p2=&b;
scanf("%d,%d",&a,&b);
if(a<b)
printf("\n%d,%d\n",a,b); return0;}p1:[1000]3000
p2:[2000]4000
b:
2000
a:
1000
_
20,30
swap的空间temp:
7000p:[1000]5000q:[2000]600020,3030,20
Hi,这是指针变量形参,传地址的!不是传数据的普通形参!voidswap(int
*p,int
*q){
inttemp; temp=*p; *p=*q; *q=temp;}swap(p1,p2);20
30
302020实参和形参必须“基类型”相同,传递的是一个4字节的地址,也是单向值传递(传地址)#include<stdio.h>intmain(){ inta,b,*p1=&a,*p2=&b;
scanf("%d,%d",&a,&b);
if(a<b)
printf("\n%d,%d\n",a,b); return0;}voidswap(int
*p,int
*q){
inttemp; temp=*p; *p=*q; *q=temp;}指针变量作函数参数——程序2voidswap(int
*p,int
*q){
int*temp; temp=p; p=q; q=temp;}main的空间p1:[1000]3000p2:[2000]4000b:
2000a:
1000swap的空间temp:[]7000p:[1000]5000q:[2000]6000[2000][1000]swap(p1,p2);20
30
1000_
20,30
20,3020,30
a、b未交换!即使是指针变量,也是单向值传(虽然传的是地址),swap中修改p、q不会影响main中的变量。而必须:*p=…;*q=…;
才能修改a、b#include<stdio.h>
intmain(){ inta,b,*p1=&a,*p2=&b;
scanf("%d,%d",&a,&b);
if(a<b)
printf("\n%d,%d\n",a,b); return0;}voidswap(int
*p,int
*q){
int*temp; temp=p; p=q; q=temp;}voidswap(int
*p,int*q){
int*temp; *temp=*p; *p=*q; *q=*temp;}指针变量作函数参数——程序3main的空间p1:[1000]3000p2:[2000]4000b:
2000a:
1000swap的空间temp:[?]7000p:[1000]5000q:[2000]6000未知空间被修改_
20,30
账户密码?Windows系统重要空间?其它程序变量?20
30
swap(p1,p2);你想把哪里改成20啊?#include<stdio.h>intmain(){ inta,b,*p1=&a,*p2=&b;
scanf("%d,%d",&a,&b);
if(a<b)
printf("\n%d,%d\n",a,b); return0;}voidswap(int
*p,int*q){
int*temp; *temp=*p; *p=*q; *q=*temp;}复习:普通变量作函数参数——程序4voidswap(intx,inty){
inttemp; temp=x;
x=y; y=temp;}main的空间p1:[1000]3000p2:[2000]4000b:
2000a:
1000swap的空间temp:?7000x:205000y:30600020swap(a,b);
302020
30
_
20,30
20,3020,30
仍未交换a、b!
普通变量做参数,更是单向值传递
(传的是数据本身),swap中修改x、y不会影响a、bswap(p1,p2);数组函数参数一维数组作函数参数——程序1#include<stdio.h>voidfun(doublea[3]);intmain(){ doubles[3]={1.1,2.2,3.3};
printf("%f",s[1]); return0;}{ a[1]=a[0]+a[2];}fun的空间main的空间s:s[0]s[1]s[2]1.12.23.3a:a[0]a[1]a[2]1.12.23.3100030001008101630083016fun(s);voidfun(doublea[3])fun的空间main的空间一维数组作函数参数——程序1#include<stdio.h>voidfun(doublea[3]);intmain(){ doubles[3]={1.1,2.2,3.3};
printf("%f",s[1]); return0;}{ a[1]=a[0]+a[2];}s:s[0]s[1]s[2]1.12.23.3double*p=s;
a:[]3000
s:[1000]10001000*(a+1)=*a+*(a+2);
*[1008]=*[1000]+*[1016];
4.44.4voidfun(doublea[3])fun(s);数组做参数?我不知道voidfun(doublea[3])我只知道voidfun(double*a)语法糖fun(p);
p:[1000]2000voidfun(doublea[])voidfun(doublea[10])100810161000语法糖voidfun(double*a)一维数组作函数参数小结intfun(int*a){ ……}参数仅是一个fun的空间a:[1000]3000
指针变量,调用时,将实参传递为数组首地址即可。
数组作函数参数
指针变量或地址作函数参数intfun(inta[]){ ……}当数组作函数参数时:intfun(inta[5]){ ……}intfun(inta[500]){ ……}这些都是语法糖
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 浙江农林大学《体育统计学(含体育测量与评价)》2023-2024学年第二学期期末试卷
- 《归去来兮辞》教学设计 2023-2024学年统编版高中语文选择性必修下册
- 天津理工大学中环信息学院《有毒有害物质检测》2023-2024学年第二学期期末试卷
- 中国美术学院《财务信息系统》2023-2024学年第二学期期末试卷
- 西藏警官高等专科学校《全媒体新闻评论》2023-2024学年第二学期期末试卷
- 大连科技学院《工程项目管理A》2023-2024学年第二学期期末试卷
- 广西工商职业技术学院《制药分离工程》2023-2024学年第二学期期末试卷
- 重庆交通大学《会计信息系统(一)》2023-2024学年第二学期期末试卷
- 泸州四川泸州市国有土地上房屋征收补偿中心(泸州市物业管理中心)招聘编外人员笔试历年参考题库附带答案详解
- 泰州2025年江苏泰州市第四人民医院招聘合同制人员27人笔试历年参考题库附带答案详解
- 中考物理复习交流
- 敬老院设备采购投标方案(技术方案)
- 充电桩采购安装售后服务方案
- 《旅行社条例》和《旅行社管理条例》对比解读
- 柳宗元抑郁而坚贞的一生
- 乡镇人大代表选举结果情况报告单
- BOPP双向拉伸薄膜及胶带生产项目环境影响报告
- 频谱仪N9020A常用功能使用指南
- 天津高考英语词汇3500
- 上海市2023年中考数学试卷(附答案)
- 《种太阳》公开课课件
评论
0/150
提交评论