C语言复习笔记 10
2017-04-12 13:24
375 查看
指针变量(pointer variable)
概述
指针变量是存放地址的变量,是一种特殊的变量,它不同于一般的变量,一般变量存放的是数据本身,而指针变量存放的是数据的地址。假设在程序中声明了1个int型的变量a,其值为68。系统为变量a分配的首地址为0X65FDF4H,p=a是存放变量a地址的指针变量,即p=a中存放的值为0x065FDF4H。
对变量a的访问有两种方式:一是直接按地址0x065FDF4H找到a的存储单元,从而对变量a进行访问;二是按系统为p=a分配的地址先找到p=a,然后根据pa的值(即变量a地址0x065FDF4H)找到变量a在内存中的存储单元,从而对变量a进行访问。对于前一种访问方式称为直接访问方式,后一种访问方式称为间接访问方式。
如果一个指针变量存放的是某个对象的地址,则称这个指针变量指向该对象。在C++程序设计中,指针变量只有确定了指向才有意义。
定义
定义指针变量的一般形式如下:类型名指针变量名1,指针变量名2,… *指针变量名n ;
空指针
空指针是一个特殊的指针,它的值是0,C语言中用符号常量NULL(在stdio.h中定义)表示这个空值,并保证这个值不会是任何变量的地址。空指针对任何指针类型赋值都是合法的。一个指针变量具有空指针值表示当前它没有指向任何有意义的东西。
void指针
(void )类型的指针叫通用指针,可以指向任何的变量,C语言允许直接把任何变量的地址作为指针赋给通用指针。但是需要注意void不能指向由const修饰的变量,例如
const int test; void * ptv; ptv = &test;第三句是非法的,只有将ptv声明为const void * ptv;,上述第三句ptv = &test才是合法的。
当需要使用通用指针所指的数据参加运算时,需要写出类型强制转换。如通用指针ptv 所指空间的数据是整型数据,p是整型指针,用此式转换:p=(int *)ptv;
区别
指针是C语言的精华部分,通过利用指针,我们能很好地利用内存资源,使其发挥最大的效率。有了指针技术,我们可以描述复杂的数据结构,对字符串的处理可以更灵活,对数组的处理更方便,使程序的书写简洁,高效,清爽。但由于指针对初学者来说,难于理解和掌握,需要一定的计算机硬件的知识做基础,这就需要多做多练,多上机动手,才能在实践中尽快掌握,成为C的高手。过去,我们在编程中定义或说明变量,编译系统就为已定义的变量分配相应的内存单元,也就是说,每个变量在内存会有固定的位置,有具体的地址。由于变量的数据类型不同,它所占的内存单元数也不相同。若我们在程序中做定义为:
int a=1,b=2; float x=3.4, y = 4.5 ; double m=3.124; char ch1='a', ch2='b';
让我们先看一下编译系统是怎样为变量分配内存的。变量a,b是整型变量,在内存各占2个字节;x,y是实型,各占4个字节;m是双精度实型,占8个字节;ch1,ch2是字符型,各占1个字节。由于计算机内存是按字节编址的,设变量的存放从内存2000单元开始存放,则编译系统对变量在内存的安放情况如下图所示。
变量在内存中按照数据类型的不同,占内存的大小也不同,都有具体的内存单元地址,如变量a在内存的地址是2000,占据两个字节后,
变量b的内存地址就为2002,变量m的内存地址为2012等。对内存中变量的访问,过去用
scanf("%d%d%f",&a,&b,&x)表示将数据输入变量的地址所指示的内存单元。那么,访问变量,首先应找到其在内存的地址,或者说,一个地址唯一指向一个内存变量,我们称这个地址为变量的指针。如果将变量的地址保存在内存的特定区域,用变量来存放这些地址,这样的变量就是指针变量,通过指针对所指向变量的访问,也就是一种对变量的“间接访问”。
设一组指针变量pa、pb、px、py、pm、pch1、pch2,分别指向上述的变量a、b、x、y、m、ch1、ch2,指针变量也同样被存放在内存,尽管所指向的变量类型不同,但是这些指针变量所占内存空间都是2个字节,而与所指向变量的类型无关。二者的关系如上图所示。
在上图中,左部所示的内存存放了指针变量的值,该值给出的是所指变量的地址,通过该地址,就可以对右部描述的变量进行访问。如指针变量pa的值为2000,是变量a在内存的地址。因此,pa就指向变量a。变量的地址就是指针,存放指针的变量就是指针变量。
难点1——关于指针中 * 的理解
在不同的场景下有不同的作用:可以用在指针变量的定义中,表明这是一个指针变量,以和普通变量区分开;使用指针变量时在前面加*表示获取指针指向的数据,或者说表示的是指针指向的数据本身。也就是说,定义指针变量时的和使用指针变量时的意义完全不同。
指针变量也可以出现在普通变量能出现的任何表达式中,例如:
int x, y, *px = &x, *py = &y; y = *px + 5; //表示把x的内容加5并赋给y,*px+5相当于(*px)+5 y = ++*px; //px的内容加上1之后赋给y,++*px相当于++(*px) y = *px++; //相当于y=(*px)++ py = px; //把一个指针的值赋给另一个指针
难点2——关于 * 和 & 的谜题
假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a和
&*pa分别是什么意思呢?
*&a可以理解为
*(&a),
&a表示取变量 a 的地址(等价于 pa),(&a)表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,&a仍然等价于 a。
&*pa可以理解为
&(*pa),*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa。
难点3 —— 关于符号 * 的总结
对星号*的总结在我们目前所学到的语法中,星号*主要有三种用途:
表示乘法,例如int a = 3, b = 5, c; c = a * b;,这是最容易理解的。
表示定义一个指针变量,以和普通变量区分开,例如int a = 100; int *p = &a;。
表示获取指针指向的数据,是一种间接操作,例如int a, b, *p = &a; *p = 100; b = *p;。
指针变量的运算
指针变量保存的是地址,本质上是一个整数,可以进行部分运算,例如加法、减法、比较等#include <stdio.h> int main(){ int a = 10, *pa = &a, *paa = &a; double b = 99.9, *pb = &b; char c = '@', *pc = &c; //最初的值 printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c); printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc); //加法运算 pa++; pb++; pc++; printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc); //减法运算 pa -= 2; pb -= 2; pc -= 2; printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc); //比较运算 if(pa == paa){ printf("%d\n", *paa); }else{ printf("%d\n", *pa); } return 0; }
运行结果: &a=0X28FF44, &b=0X28FF30, &c=0X28FF2B pa=0X28FF44, pb=0X28FF30, pc=0X28FF2B pa=0X28FF48, pb=0X28FF38, pc=0X28FF2C pa=0X28FF40, pb=0X28FF28, pc=0X28FF2A 2686784
指针变量加减运算的结果跟数据类型的长度有关,而不是简单地加 1 或减 1
我们知道,数组中的所有元素在内存中是连续排列的,如果一个指针指向了数组中的某个元素,那么加 1 就表示指向下一个元素,减 1 就表示指向上一个元素,这样指针的加减运算就具有了现实的意义。
不过C语言并没有规定变量的存储方式,如果连续定义多个变量,它们有可能是挨着的,也有可能是分散的,这取决于变量的类型、编译器的实现以及具体的编译模式,所以对于指向普通变量的指针,我们往往不进行加减运算,虽然编译器并不会报错,但这样做没有意义,因为不知道它后面指向的是什么数据。
指针变量除了可以参与加减运算,还可以参与比较运算。当对指针变量进行比较运算时,比较的是指针变量本身的值,也就是数据的地址。如果地址相等,那么两个指针就指向同一份数据,否则就指向不同的数据。
相关文章推荐
- C语言接口与实现-创建可重用软件的技术 (笔记10)
- c语言复习笔记(2)--标准库中的I/O
- sqlite学习笔记10:C语言中使用sqlite之查询和更新数据
- 自学笔记-C语言复习2015年6月25日
- 自学笔记—C语言复习2015年6月23日
- C语言复习笔记二:输入输出
- 自学笔记-C语言复习2015年7月4日
- C语言复习笔记(二)
- MYSQL复习笔记10-连接
- 自学笔记-C语言复习2015年7月2日
- C语言复习串讲课堂笔记
- c语言复习笔记——内存分配问题
- c语言复习笔记——sizeof()
- C语言复习笔记(三)
- c语言学习笔记(10)——结构体
- c语言复习笔记(1)--从HelloWorld说起
- c语言复习笔记--指针定义
- C语言复习笔记-17种小算法-解决实际问题
- iOS复习笔记10:使用Block
- 自学笔记-C语言复习2015年7月3日