第8章_地址和指针

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机内存中的一片段
内存编号 存储单元
int x,y,z; x=5;y=3;z=2;
2001 2002 2003 2010 2011 2012 2013 2014 2015
又比如有如下定义: short int a; int b; folat x; a=100;b=23; x=12.34
指针变量中存放的是地址,为什么一定要定义基类型呢?
§ 8.3 给指针变量赋值
一.给指针变量赋地址值 一个指针变量可以通过不同的方式获得一个确定 的地址值,从而使它指向一个具体的对象. 1.通过求地址运算符&来获得地址值 单目运算符&用来求出运算对象的地址.所以如果有 以下定义: int k=1,*q,*p; 则: q=&k; 是什么意思? 2.通过指针变量获得地址值. 语句 p=q; 是什么意思? 3.通过标准函数获得地址值. 可以通过调用库函数malloc和calloc给指针变量赋值
§8.2 指针变量的定义和指针变量的基类型
1 .定义一个指针变量的一般语法形式如下:
类型名 *指针变量名1, *指针变量名2,…… ;
例如: 例如:
int
*a_pointer,*b; *f; *c1,*c2;
double char
在定义指针变量时要注意两点: (1) 指针变量前面的“*”,表示该变量的类型为指针型变 量。 例: float *pointer_1; 指针变量名是pointer_1 ,而不是* pointer_1 。 (2) 在定义指针变量时必须指定基类型。 需要特别注意的是,只有整型变量的地址才能放到指向 整型变量的指针变量中。下面的赋值是错误的∶ float a; int * pointer_1; pointer_1=&a;
若有定义语句:其中的意思是? int **p,*s,k=20; s=&k; p=&s;
对"&"和"*"运算符说明: 如果已执行了语句 pointer_1=&a; (1)&* pointer_1的含义是什么? “&”和“*”两个运算符的优先级别相同,但按 自右而左方向结合,因此先进行* pointer_1的运 算,它就是变量a,再执行&运算。因此,&* pointer_1与&a相同,即变量a的地址。 如果有pointer_2 =&* pointer_1 ;它的作用 是将&a(a的地址)赋给pointer_2 ,如果 pointer_2原来指向b,经过重新赋值后它已不再指 向b了,而指向了a。
变量a,直接存可表示为:
a 12 1012 1013 1014 1015
间接存可表示为: a_pointer 1012 1037 1038 1039 1040
① ②
12 a 1012 1013 1014 1015 ③ 12
所谓"指向"就是通过地址来体现的.当我们把变 量a的地址1012放在特殊变量a_pointer中以后,就会 在a_pointer和变量a之间建立起一种联系,即:通过 a_pointer能知道a的地址,从而找到变量a的内存单 元.前面的红色箭头表示"指向"这种关系. 由于通过地址能找到所需要的变量单元,那我们 可以说,地址指向该变量单元(如同说,一个房间 号"指向"某一房间一样).因此在C语言中,将地 址形象化地称为"指针".意思是通过它能找到以它 为地址的内存单元(例如根据地址1012就能找到变量a 的存储单元,从而读取其中的值)
也就是说我们对每一个变量的操作,分为: ①直接找到编译时给变量分配的相应的内存地址 ②再操作这个地址中的内容 .
又比如有如下定义: int a,b,k; folat x; a=12; b=23; x=12.34 k=a+b;
1012-1015 1016-1019 1020-1023 1024-1027 1025-1028 1029-1032 1033-1036 1037-1040 1041-1044
§ 8.4 对指针变量的操作
一.通过指针来引用一个存储单元 我们知道,C语言提供了一个称作为"间接访问运 算符"的单目运算符*.当指针变量中存放了一个确切 的地址值时,就可以用"间接访问运算符"通过指针来 引用该地址的存储单元. 假定有以下定义和语句: int *p,i=10,j; p=&i; 则以下赋值语句的作用是? j=*p; j=&(*i); j=*p+1;
运行情况如下: 5,9↙ a=5,b=9 max=9,min=5 当输入a=5,b=9时,由于a<b, 将p1和p2交换。交换前的情况见图 (a),交换后见图(b)。
二.给指针变量赋"空值" 除了给指针变量赋地址值外,还可以给指针变量赋 NULL值. 如: int a,*p; p=&a; p=NULL; //执行本语句后,称p为空指针. 通过ASCII码表可知: NULL的值为0; 所以p=NULL p='\0' p=0
(2) *&a的含义是什么? 先进行&a运算,得a的地址,再进行*运算。即 &a所指向的变量,也就是变量a。*&a和*pointer_ 1的作用是一样的,它们都等价于变量a。即*&a与 a等价。 (3) (*pointer_1)++相当于a++。注意括号是必 要的,如果没有括号,就成为了*pointer_1++,从 附录可知:++和*为同一优先级别,而结合方向为自 右而左,因此它相当于*(pointer_1++)。由于++在 pointer_1的右侧,是“后加”,因此先对pointer_1的原 值进行*运算,得到a的值,然后使pointer_1的值改 变,这样pointer_1不再指向a了。
第八章
§8.1变量的地址和指针
计算机内存的结构: 计算机内存中最小的存储单位是位(bit); 计算机内存的基本存储单位是字节(Btye);它是由8个 bit位组成的. 即1Btye=8bit 计算机为了方便管理内存中许许多多的字节,就把每 一个字节进行编号,这个编号就是“地址” 。如果在 程序中定义了一个变量,在对程序进行编译时,系 统就会给这个变量分配内存单元。
打个比方,为了开一个A抽屉,有两种办法,一种是将A钥匙带在 身上,需要时直接找出该钥匙打开抽屉,取出里面的东西.另一 种办法是:为安全起见,将A钥匙放到另一抽屉B中锁起来.如果 想在A抽屉里面取东西,就先找出B钥匙,打开B抽屉,取出A 钥匙,拿着A钥匙打开A抽屉,最后取出A抽屉中的东西, 这就是"间接存取". a 变量a,直接取可表示为: 间接取可表示为: a_pointer 1012 1037 1038 1039 1040 a 12 1012 1013 1014 1015 12 1012 1013 1014 1015
int a,b,k; folat x; a=12; b=23; x=12.34 k=a+b;
1012-1015 1016-1019 1020-1023 1024-1027 1025-1028 1029-1032 1033-1036 1037-1040 1041-1044
a k b x
a_pointer
例8.1 通过指针变量访问整型变量 #include <stdio.h> void main ( ) {int a,b; int *pointer_1,*pointer_2; a=100;b=10; pointer_1=&a; pointer_2=&b; printf("%d,%d\n",a,b); printf("%d,%d\n",*pointer_1,*pointer_2); }
if(p<q) printf("p points to loewer memory than q.\n"); if(p=='\0') printf("p points to NULL.\n")
§8.5函数之间地址值的传递
一.形参为指针变量时实参和形参之间的数据传递 若函数的形参为指针类型时,在调用此函数时,对 应的实参必须是基类型相同的地址值或者是已指向 某个存储单元的指针变量.
a k b x
以上的运算都是按变量的地址来存取变量的值 的,也就是前面所说的"直接存取"方式. 实事上我们还可以采用另一种称之为"间接存取 "的方式,即将变量a的地址存放在另一个特殊变量 a_pointer中. 假设我们定义了一个变量a_pointer用来存放整型 变量a地址,它被分配地址为(1037-1040)这4个字 节。可以通过语句:a_pointer =&a; 将a的地址(1012)存放到i_pointer中。这时, i_pointer的值就是(1012) ,即变量a所占用单元 的起始地址。要存取变量i的值,可以采用间接方 式:先找到存放“a的地址”的变量a_pointer , 从中取出a的地址(1012),然后到1012-1015这4字 节中取出a的值12。
#include<stdio.h> main() { int a[0],a[1],a[2],a[3],a[4]; a[0]=11;a[1]=22;a[2]=33; a[3]=44;a[4]=55; int *p,*q; p=&a[0]; q=&a[2]; q=p+2; q++; q++; q--; p++; i=*p;j=*q; }
例8.2 输入a和b两个整数,按先大后小的顺序输出 a和b. #include <stdio.h> void main() { int *pa,*pb,*p,a,b; scanf("%d,%d",&a,&b); pa=&a; pb=&b; if(a<b) {p=p1;p1=p2;p2=p;} printf(″a=%d,b=%d\n\n″,a,b); printf(″max=%d,min=%d\n″,*p1,*p2); }
二.移动指针 所谓移动指针就是对指针变量加上或减去一个整 数,或能过赋值运算,使指针变量指向相邻的存储单元. 因此,只有当指针指向一串连续的存储单元时,指针的 移动才有意义. 当指针指向一串连续的存储单元时,可以进行移动 指针的操作, 当有两个指针指向同一串连续的存储单元时,可对 这两个指针进行加减运算, 除此之外,不可以对指针进行任何其他的算术运算,
1012-1015 1016-1019 1020-1023 1024-1027 1025-1028 1029-1032 1033-1036 1037-1040 1041-1044
a[0] a[1] a[2] a[3] a[3] a[4]
三.指针比较 在关系表达式中可以对两个指针进行比较.例如 p,q是两个指针变量,以下语句是完全正确的:
指针和指针变量的定义: 一个变量的地址称为该变量的“指针”。 求一个普通变量的地址可以用求地址运算符&完成, 如: int i,t; //&i,&t将会求出变量i,t的地址. float f; //&f将求出变量f的地址. 如果有一个变量专门用来存放另一变量的地址(即 指针),则它称为“指针变量”。前面的a_pointer 指针变量的值(即指针变量中存放的值)是地址 就是一个指针变量。 (即指针)。请区分“指针”和“指针变量”这两个概 念。
a 1012 1013 b
1018
1019 x
1020
1021
1201
1202
1203
1204
一般情况下,我们在程序中只需指出变量名, 无需知道每个变量在内存中的具体地址值,每个 变量与具体地址的联系由C编译系统来完成.程序 中我们对变量进行存取操作,实际上也就是变量 的地址所对应的存储单元进行操作,这种直接按 变量的地址存取变量值的方式称为"直接存取"方 式.
给指针变量赋值时注意: 1.单目取地址运算符&只能应用于求 变量和数组元素,的地址,不能用于求 表达式,常量,或者被说明为register的 变量. 2.&运算符必须放在运算对象的左边, 且运算对象的类型必须与指针变量的 基类型相同. 3.请牢记,指针变量中只能存放地址 (指针),不要将一个整数(或任何 其他非地址类型的数据)赋给一个指 针变量。 int i,k,*p,*q; float *f; p=&i; q=&(k+i); f=&k; q=i;
相关文档
最新文档