您好,欢迎访问三七文档
第9章指针指针是C语言中的重要概念,也是C语言的重要特色。使用指针,可以使程序更加简洁、紧凑、高效。9.1指针和指针变量的概念9.2指针变量的定义与应用9.3数组的指针和指向数组的指针变量9.4字符串的指针和指向字符串的指针变量9.5返回指针值的函数9.6指针数组与主函数main()的形参9.7函数的指针和指向函数的指针变量9.1指针和指针变量的概念1.内存地址──内存中存储单元的编号(1)计算机硬件系统的内存储器中,拥有大量的存储单元(容量为1字节)。为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”。每个存储单元都有一个惟一的地址。(2)在地址所标识的存储单元中存放数据。注意:内存单元的地址与内存单元中的数据是两个完全不同的概念。2.变量地址──系统分配给变量的内存单元的起始地址假设有这样一个程序:main(){intnum;scanf(%d,&num);printf(num=%d\n,num);}C编译程序编译到该变量定义语句时,将变量num登录到“符号表”中。符号表的关键属性有两个:一是“标识符名(id)”,二是该标识符在内存空间中的“地址(addr)”。为描述方便,假设系统分配给变量num的2字节存储单元为3000和3001,则起始地址3000就是变量num在内存中的地址。3.变量值的存取──通过变量在内存中的地址进行系统执行“scanf(”%d“,&num);”和“printf(”num=%d\n“,num);”时,存取变量num值的方式可以有两种:(1)直接访问──直接利用变量的地址进行存取1)上例中scanf(“%d”,&num)的执行过程是这样的:用变量名num作为索引值,检索符号表,找到变量num的起始地址3000;然后将键盘输入的值(假设为3)送到内存单元3000和3001中。此时,变量num在内存中的地址和值,如图9-1所示。2)printf(num=%d\n,num)的执行过程,与scanf()很相似:首先找到变量num的起始地址3000,然后从3000和3001中取出其值,最后将它输出。(2)间接访问──通过另一变量访问该变量的值C语言规定:在程序中可以定义一种特殊的变量(称为指针变量),用来存放其它变量的地址。例如,假设定义了这样一个指针变量num_pointer,它被分配到4000、4001单元,其值可通过赋值语句“num_pointer=#”得到。此时,指针变量num_pointer的值就是变量num在内存中的起始地址3000,如图9-1所示。通过指针变量num_pointer存取变量num值的过程如下:首先找到指针变量num_pointer的地址(4000),取出其值3000(正好是变量num的起始地址);然后从3000、3001中取出变量num的值(3)。(3)两种访问方式的比较两种访问方式之间的关系,可以用某人甲(系统)要找某人乙(变量)来类比。一种情况是,甲知道乙在何处,直接去找就是(即直接访问)。另一种情况是,甲不知道乙在哪,但丙(指针变量)知道,此时甲可以这么做:先找丙,从丙处获得乙的去向,然后再找乙(即间接访问)。4.指针与指针变量(1)指针──即地址一个变量的地址称为该变量的指针。通过变量的指针能够找到该变量。(2)指针变量──专门用于存储其它变量地址的变量指针变量num_pointer的值就是变量num的地址。指针与指针变量的区别,就是变量值与变量的区别。(3)为表示指针变量和它指向的变量之间的关系,用指针运算符“*”表示。例如,指针变量num_pointer与它所指向的变量num的关系,表示为:*num_pointer,即*num_pointer等价于变量num。因此,下面两个语句的作用相同:num=3;/*将3直接赋给变量num*/num_pointer=#/*使num_pointer指向num*/*num_pointer=3;/*将3赋给指针变量num_pointer所指向的变量*/[Return]9.2指针变量的定义与应用9.2.1指针变量的定义与相关运算[案例9.1]指针变量的定义与相关运算示例。/*案例代码文件名:AL9_1.C*/main(){intnum_int=12,*p_int;/*定义一个指向int型数据的指针变量p_int*/floatnum_f=3.14,*p_f;/*定义一个指向float型数据的指针变量p_f*/charnum_ch=’p’,*p_ch;/*定义一个指向char型数据的指针变量p_ch*/p_int=&num_int;/*取变量num_int的地址,赋值给p_int*/p_f=&num_f;/*取变量num_f的地址,赋值给p_f*/p_ch=&num_ch;/*取变量num_ch的地址,赋值给p_ch*/printf(“num_int=%d,*p_int=%d\n”,num_int,*p_int);printf(“num_f=%4.2f,*p_f=%4.2f\n”,num_f,*p_f);printf(“num_ch=%c,*p_ch=%c\n”,num_ch,*p_ch);}[程序演示]程序运行结果:num_int=12,*p_int=12num_f=3.14,*p_f=3.14num_ch=p,*p_ch=p程序说明:(1)头三行的变量定义语句──指针变量的定义与一般变量的定义相比,除变量名前多了一个星号“*”(指针变量的定义标识符)外,其余一样:数据类型*指针变量[,*指针变量2……];注意:此时的指针变量p_int、p_f、p_ch,并未指向某个具体的变量(称指针是悬空的)。使用悬空指针很容易破坏系统,导致系统瘫痪。(2)中间三行的赋值语句──取地址运算(&)取地址运算的格式:&变量例如,&num_int、&num_f、&num_ch的结果,分别为变量num_int、num_f、num_ch的地址。注意:指针变量只能存放指针(地址),且只能是相同类型变量的地址。例如,指针变量p_int、p_f、p_ch,只能分别接收int型、float型、char型变量的地址,否则出错。(3)后三行的输出语句──指针运算(*)使用直接访问和间接访问两种方式,分别输出变量num_int、num_f、num_ch的值。注意:这三行出现在指针变量前的星号“*”是指针运算符,访问指针变量所指向的变量的值,而非指针运算符。[案例9.2]使用指针变量求解:输入2个整数,按升序(从小到大排序)输出。/*案例代码文件名:AL9_2.C*//*程序功能:使用指针变量求解2个整数的升序输出*/main(){intnum1,num2;int*num1_p=&num1,*num2_p=&num2,*pointer;printf(“Inputthefirstnumber:”);scanf(“%d”,num1_p);printf(“Inputthesecondnumber:”);scanf(“%d”,num2_p);printf(“num1=%d,num2=%d\n”,num1,num2);if(*num1_p*num2_p)/*如果num1num2,则交换指针*/pointer=num1_p,num1_p=num2_p,num2_p=pointer;printf(“min=%d,max=%d\n”,*num1_p,*num2_p);}[程序演示]程序运行情况:Inputthefirstnumber:9←┘Inputthesecondnumber:6←┘num1=9,num2=6min=6,max=9程序说明:(1)第5行的if语句如果*num1_p*num2_p(即num1num2),则交换指针,使num1_p指向变量num2(较小值),num2_p指向变量num1(较大值)。(2)printf(“min=%d,max=%d\n”,*num1_p,*num2_p);语句:通过指针变量,间接访问变量的值。本案例的处理思路是:交换指针变量num1_p和num2_p的值,而不是变量num1和num2的值(变量num1和num2并未交换,仍保持原值),最后通过指针变量输出处理结果。9.2.2指针变量作函数参数1.指针变量,既可以作为函数的形参,也可以作函数的实参。2.指针变量作实参时,与普通变量一样,也是“值传递”,即将指针变量的值(一个地址)传递给被调用函数的形参(必须是一个指针变量)。注意:被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。[案例9.3]使用函数调用方式改写[案例9.2],要求实参为指针变量。/*案例代码文件名:AL9_3.C*//******************************************************//*exchange()功能:交换2个形参指针变量所指向的变量的值*//*形参:2个,均为指向整型数据的指针变量*//*返回值:无*//******************************************************/voidexchange(int*pointer1,int*pointer2){inttemp;temp=*pointer1,*pointer1=*pointer2,*pointer2=temp;}/*主函数main()*/main(){intnum1,num2;/*定义并初始化指针变量num1_p和num2_p*/int*num1_p=&num1,*num2_p=&num2;printf(“Inputthefirstnumber:”);scanf(“%d”,num1_p);printf(“Inputthesecondnumber:”);scanf(“%d”,num2_p);printf(“num1=%d,num2=%d\n”,num1,num2);if(*num1_p*num2_p)/*即num1num2)*/exchange(num1_p,num2_p);/*指针变量作实参*//*输出排序后的num1和num2的值*/printf(“min=%d,max=%d\n”,num1,num2);}[程序演示]程序运行情况:Inputthefirstnumber:9←┘Inputthesecondnumber:6←┘num1=9,num2=6min=6,max=9调用函数exchange()之前、之时、结束时和结束后的情况,如图9-5所示。形参指针变量pointer1(指向变量num1)和pointer2(指向变量num2),在函数调用开始时才分配存储空间,函数调用结束后立即被释放。虽然被调用函数不能改变实参指针变量的值,但可以改变它们所指向的变量的值。总结:为了利用被调用函数改变的变量值,应该使用指针(或指针变量)作函数实参。其机制为:在执行被调用函数时,使形参指针变量所指向的变量的值发生变化;函数调用结束后,通过不变的实参指针(或实参指针变量)将变化的值保留下来。[案例9.4]输入3个整数,按降序(从大到小的顺序)输出。要求使用变量的指针作函数调用的实参来实现。/*案例代码文件名:AL9_4.C*//******************************************************//*exchange()功能:交换2个形参指针变量所指向的变量的值*//*形参:2个,均为指向整型数据的指针变量*//*返回值:无*//******************************************************/voidexchange(int*pointer1,int*pointer2){inttemp;temp=*pointer1,*pointer1=*pointer2,*pointer2=temp;}/*主函数main()*/main(){intnum1,num2,num3;/*从键盘上输入3个整数*/printf(“Inputthefir
本文标题:c语言指针教程
链接地址:https://www.777doc.com/doc-7027505 .html