指针与指针变量_第1页
指针与指针变量_第2页
指针与指针变量_第3页
指针与指针变量_第4页
指针与指针变量_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第五章 指针 之 第一节 指针与指针变量1.指针的基本概念 计算机内存是有一片连续的存储单元组成,操作系统给每个单元一个编号,这个编号称为内存单元的地址,每个存储单元占内存一个字节。 定义变量时,系统就按照其类型为变量分配一块连续的存储单元。 则这块存储单元的首地址称为该变量的指针(也称该变量的地址)。 如:float f ; 假设分配给f的是地址为1500、1501、1502、1503的四个连续字节。 则称地址1500是变量f的指针(或说变量f的地址是1500)。 所以,变量的地址就是变量的指针。 第五章 指针 之 第一节 指针与指针变量n先来看 卡片管理系统 假设有许多存储不同数据的卡片,

2、如图。想对这些数据快速存取,一个好方法就是对每张卡片编号,再为每张卡片取个名字,让名字和编号一一对应起来。 这样就能通过名字存取卡片上的数据,比如指出卡片名f,就可以由对应地址1500处取出数据456.789。123您好!456.7891500卡片上数据卡片编号 1500015002卡片名字 abchipf. 注意:p 是一种特殊的卡片,它存储的是卡片 f的编号,则通过p 也能间接地存取卡片f的数据。 图5.1第五章 指针 之 第一节 指针与指针变量n变量值的存取与卡片数据存取相类似。 每个变量都有名字和地址。同样是使用变量名通过相应地址存取数据。可以把图5.1理解成变量存储的情况,如图5.2

3、。 假设变量f为float型。则读取f的值是从地址1500开始的四个字节中取出数据456.789。这种称为“直接存取”方式。 特殊变量p存储了变量f的地址。则可以通过访问p变量,可以得到地址1500,再访问1500的存储单元,也可以得到f的值456.789。这种称为“间接存取“方式。 变量的值地址编号 1000500015001002变量名 abchipf.123您好!456.7891500 图5.2第五章 指针 之 第一节 指针与指针变量 象p变量这种,专门存放其他变量的地址的变量,称为指针变量。 如图5.2,指针变量p里已经存储了f 变量的地址,我们又说指针变量p指向了变量 f 。2。指针

4、变量的定义 定义的一般形式: 类型名类型名 * 标识符标识符 ; 如: int i, * ip, * jp ; /* 定义了ip和jp两个可以指向整型变量的指针变量*/ float f, *p; /* 定义了一个可以指向float型变量的指针变量p*/ 注意:a.定义了一个指针变量,在没有对它赋值前,它指向的存储单元是不确定的。 b.一个指针变量只能指向其类型相同的变量第五章 指针 之 第一节 指针与指针变量3.指针变量的赋值 1). 通过地址运算符&赋值 “&”是单目运算符,作用是对其右边的对象进行取地址。 如: float f, *p; p=&f; /* 这样指针变

5、量p就指向变量f了 */ 2).指针变量初始化。 如: float f, *p=&f; 变量p 指向 ff3d 变量fff3df的值第五章 指针 之 第一节 指针与指针变量3)通过其他指针变量赋值 可以把一个指针变量的地址值赋给另一个指针变量,这样两个指针变量均指向同一个地址。 如: int i, * p1=&i, * p2; p2=p1; 指向 2f3a 变量p1 变量i 变量p2 注意,当把一个指针变量的地址值赋给另一个指针变量时,赋值号两边指针变量所指的数据类型必须相同。2f3ai的值2f3a第五章 指针 之 第一节 指针与指针变量如: int i, * pi=&

6、i; float *pf; pf=pi; /* 这句是非法的*/ 4). 用NULL给指针变量赋空值 可以给指针变量赋空值,如: p= NULL ; NULL是在 stdio.h头文件中定义的预定义标识符,因此在使用 NULL时,应该在程序中加上文件包含#include“stdio.h”。在C语言中当指针值为NULL时,指针不指向任何有效数据。由于NULL与整数0相对应,所以下面三条语句等价: p= NULL;或 p= 0; 或 p=0 ; NULL可以赋值给指向任何类型的指针变量。第五章 指针 之 第一节 指针与指针变量5).通过调用标准库函数赋值 可以调用库函数malloc和calloc在

7、内存中开辟动态存储单元,并把所开辟的动态存储单元的首地址赋给指针变量。由于这两个函数返回的是“void。”无类型指针类型,因此将它们的返回值赋值给指针变量时要进行强制类型转换。(1)malloc函数 调用该函数,在内存的动态存储区中分配一个指定长度(以字节为单位)的连续存储空间,如果调用该函数成功,则返回所分配空间的首地址,如果分配不成功测返回NULL。 调用形式为: malloc(表达式) 如: int *p; p=( int *)malloc (sizeof (10*int );分配成功,p就能得到20个字节空间的首地址第五章 指针 之 第一节 指针与指针变量 (2)calloc 函数 调

8、用该函数,在内存动态存储区中分配一块连续的存储空间. 函数调用形式为: calloc(n,size) 如:int *p; p=( int *)calloc (20,sizeof (int ); /* 效果等同于上面的malloc例子*/ 指向20个字节首地址 p f73b f73c f73d(3)free函数 调用该函数,用来释放由 malloc或。alloc函数分配的存储空间,调用该函数不返回任何值。函数调用形式为: free(指针变量) 其中指针变量应指向调用malloc或calloc时所分配存储区的首地址, 如 : free(p);f73b 第五章 指针 之 第二节 指针运算符52 方针

9、运算符 指针运算符 “ * ” 和 取地址运算符“ & ” 521 指针运算符“ * ” 指针运算符的运算对象必须放在指针运算符的右侧,是用来存取相应的存储单元中的数据。运算符和* 都是单目运算符,它们具有相同的优先级,结合方向均为“从右到左”. 例如: int i123,j,* p; p= i; 则 j=*p;和j=*&i ;都将把变量 i的值赋给变量 j。而* p= 456; 和 * i= 456;都将把整数456赋给变量 i。 第五章 指针 之 第二节 指针运算符 所以: 1. *&i 等价于&*i等价于变量i. 2当一个指针变量 p指向某变量 i时(p=

10、 i;),则表达式* p与变量 i等价。例如: p= i; printf(”dn”,* p) /* 相当于 printf(”dn”,i);* / j= (* p)+ +; /* 相当于j= i十十;* / 注意表达式(* p)+ + 中的括号不能省略,如果没有括号,则* p+等价于*(p+),此时先使用变量i的值,再使p的值改变,这样p就不再指向变量i了。第五章 指针 之 第二节 指针运算符 指针变量的值是可以改变的. 通过* p方式存取它所指向变量的值是以间接存取的形式进行的.如: int i= 1,j= 2,* p; P= i; * p = 100;/* 相当于i + = 100;* /

11、P= j; (*p) - -;/* 相当于j - -;* / 另外,注意: 若有 int i, *p=&i; /* 相当于 int I , * p;p= i;* / 则 1. *p 等价于 i 等价于 *&i 2. *p 等价于 p 3* i是非法的表达式,因为i不是地址,也不是指针变量。而指针运算符“ * ”的运算对象必须是指针变量或地址。第五章 指针 之 第二节 指针运算符例 51由键盘机一个正整数,求出其最高位数字。用指针变量来完成本题。 main() long i,*p; pi; printf(请输人一个正整数:”); scanf(”ld,p); /* 本语句等价于sc

12、anf(”ld,i);* / while(* P= 10)* P/= 10;/* 求出该正整数的最高位数字* / printf( 最高位数字是:ld。n”,* P); 运行结果: 请输人一个正整数:56789 最高位数字是:5。 语句P=&i ;是不可少的,若指针变量P在使用之前未赋初值,它可能指向内存中任意一个地址,可能导致程序出现意想不到的错误。第五章 指针 之 第二节 指针运算符522 无类型指针 可定义一个指针变量,指向 void *类型,在将它的值赋给另一个指针变量时,要进行强制类型转换。 int * pl; char * p2 ; void *q; /*定义 q为无类型指针

13、变量* / q= malloc( slzeof(int) ); p1= (int* )q; /* 将 q的地址赋值给指针变量 P1,q与 p1指向同一地址* / * pl= 0X4142; /* 对 pl所指的内存赋值 0 x4124(即十进制数 16706)* / p2= (char *)q ; /* 将 q的地址赋值给指针变量 p2,q与 p2指向同一地址* / printf(%d,c,cn”,* pl,* p2,* (p21); free(q); 以上程序段运行的结果是: 16706,B,A第五章 指针 之 第二节 指针运算符 可以用无类型指针q指向内存中的一块存储单元,当用不同类型的指

14、针与q指向同一地址时,可存取不同类型的数据。若指向整型类型的指针ql指向q所指的地址时,则可用* pl存取整型数据;若指向字符型的指针 p2指向 q所指的地址时,则可用* p2存取字符型数据,上述程序段中,0 x41(即十进制数 65)是字符A 的 ASCll码。 也可以用强制类型转换,把一个指针的值赋值给一个无类型指针。 例如: float f,* p3f; void * q; q= (void * )p3; 则此时q和p3都指向实型变量f。第五章 指针 之 第三节 指针与数组531 指针与一维数组1一维数组和数组元素的地址 一个数组的元素在内存中是连续存放的,数组第一个元素的地址称数组第一

15、个元素的地址称数组的首地址数组的首地址。在C语言中,数组名是该数组的首地址数组名是该数组的首地址。例如有以下定义语句: int a10,*p; 则语句p= a;和p= ao;是等价的( 即a等价于&ao ),都表示指针变量p指向a数组的首地址。 数组首地址的值是一个地址常量,是不能改变的。因此,语句 a= p;或 a;都是非法的.第五章 指针 之 第三节 指针与数组在C语言中, 若定义 int a6;则: 数组的0元素a0的地址是a (等价于 &a0); 数组的1元素 a1的地址是 a+1(等价于&a1 ); 数组的2元素a2的地址是a+2(等价于&a2 );

16、数组的i元素a i 的地址是a+ i(等价于&ai );例如,有下述程序段:例如,有下述程序段: int a6= 1,2,3,4,5,6,* p= a; /* p指向整型数组指向整型数组 a的首地址的首地址* / double d 6= 1l,22,33,44,55,66,* q= d;假设数组假设数组a的首地址是的首地址是2000,假设数组,假设数组d的首地址是的首地址是3000.第五章 指针 之 第三节 指针与数组 则上述两个数组分配的内存情况如图 54所示,应注意整型数组(int)每下移一个元素地址加2字节,双精度实型数组(double)每下移一个元素地址加 8字节。 图5.4

17、a第五章 指针 之 第三节 指针与数组 数组数组d 的内存情况的内存情况: 图图5.4 b 此时的此时的 q+1 等价于等价于 d+1, 也等价于也等价于 &d1 q+i 等价于等价于 d+i, 也等价于也等价于 &di第五章 指针 之 第三节 指针与数组2通过一维数组名所代表的地址存取数组元素通过一维数组名所代表的地址存取数组元素 根据指针运算符根据指针运算符“ * ”的运算的运算 规则知规则知*(b十十i)与元素)与元素ai等价等价 例如,下述程序段:例如,下述程序段: int a 1,2,3,4,5,6,7,8,9,10 ; * (a十十5)= 50; /*相当于相当于a

18、5= 5O;* / scanf(”%d”,&a8); /*相当于相当于scanf(%d ,a十十8););* / printf(”dn,* (a5);); /*相当于相当于 printf”dn,a 5 ););* /第五章 指针 之 第三节 指针与数组3通过指针运算符通过指针运算符“ * ”存取数组元素存取数组元素 设有如下程序段:设有如下程序段: int a10 ,* p; p = a; 则则 *(pi)与元素)与元素a i 等价等价 以下程序段合法以下程序段合法: int a 1,2,3,4,5,6,7,8,9,10,*pa; *(p+5)=50;/*相当于相当于a5=50; */ scanf(”d”,a8););/*相当于相当于 scanf(”d”,p8););*/ printf(”d n”,*( p5 ); /*相当于相当于 printf ( ”dn”,a5 ) ;*/第五章 指针 之 第三节 指针与数组4通过带下标的指针变量存取数组元素 C语言中的下标运算符“ ”可以构成表达式,假设p为指针变量且指向数组首元素,i为整型表达式,则可以把pi看成是表达式,首先按p+i计算地址,然后再存取此地址单元中的值。因此pi与*(p + i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论