1、
指针与变量
定义一个变量,再定义一个指向该变量类型的指针,把该变量的地址赋给此指针,然后通过此指针访问该变量,教科书上都是这样说的,但恐怕没有人这样用,因为还不如直接访问变量名直截了当。问题是为什么这两种方法都可以访问那个特定内存单元呢?答案只有一个:变量名和变量的指针含有相同的信息:1那个特定内存单元地址,2连续访问单元数目(对象所占的字节数)。对于指针来讲1号信息通过赋值实现(可改变),2号信息通过定义实现,不可改变(char 为1,int 为 2),以后就会看到只要定义指针2号信息必须定义(要素1),这就是为什么抽象指针不能访问对象的原因(计算机不知道到底该读几个单元)。对于变量名来讲这两条信息都是通过定义实现的,而且不可改变。
一般说来,变量的指针总是指向变量的低地址;变量的指针+1总是加上连续访问单元数目。灵活的改变这两个信息就可以灵活的使用指针
例:
unsigned int v;
unsigned char word_hi , word_low;
char * p;
v = 0x1234;
p = ( char * )&v;
word_hi = *p++;
word_low = *p;
这就是一个把一个整数即可以当整数访问,也可以当字节访问的方法。灵活的利用这个例子你也可以把数组当作任意类型的数据进行访问。
2、
指针与数组
指针与数组的关系非常密切,数组所有的操作都可以用指针来实现。用指针也可以把一段内存区域当数组来访问。
数组名表示存放数组内存单元的首地址,是这个地址的标号。数组总占内存的一段连续的存储单元。
①、指针与一维数组
unsigned
char
array[10];
unsigned
char
*p
下面2种方法都可以把指针指向数组
p = array;
p = &arrary [0];
引用数组元素的方法
p + i 和array + i都是数组元素array的地址
*(p + i) 和*(array + i)都是数组元素array
*(p + i)和 p 都是数组元素array
p + i是指向数组的下一个元素,实际地址是p+i*d,d是连续访问单元数目(对象所占的字节数)。
定义并赋值一个指针p之后,就可以用 p的方式把一段内存区域当数组来访问。
②、指针与多维数组
Unsigned char t[3][4];
Unsigned char * p;
P = &t[0][0];
//若p = t会产生警告错误
//此时整个t数组被看作一维数组
*(p+4)与t[1][1]、p[4]等同,表示t[1][1]的值
Unsigned char t[3][4];
Unsigned char (*ph)[4];
Ph = t;
//此时整个t数组被看作具有三个 一维数组t_col[4](包含4个char类型元素)元素的一维数组t_row[3]
ph指向t_row数组的第0个元素(一维数组)与t[0][0]的地址值相同,不等同于*(ph)。
ph+2指向t_row数组的第二个元素(一维数组);与t[2][0]的地址值相同,不等同于*(ph+2)。
*(ph+2)指向t_col的第0个元素(char类型)与ph[2],&t[2][0]等同,表示t[2][0]的地址
*(*(ph+2))与t[2][0]等同,表示t[2][0]的值
*(ph+2)+1与&t[2][1]等同,表示t[2][1]的地址
*(*(ph+2)+1)与t[2][1]、(*(ph+2))[1]、ph[2][1]等同,表示t[2][1]的值
因为ph 表示的是一个指针,此指针指向包含4个元素的一维数组。或者说ph是一个指针, 此指针所指对象是包含4个元素的一维数组,此一维数组是作为一个整体被此指针访问,连续访问单元数目是4*1(char型)。整体访问数组的办法是给出这个数组的指针。
这个例子很容易与后面讲到的指针数组相混淆,注意区别。
虽然上面列举了很多访问数组元素的方法,只不过想说明每种指针的不同而已;建议访问数组元素还是用p++,*p这样的方式来访问,不要用*(p+1)来访问。前一种方法指针直接指向要访问的元素,而后一种方法只是把指针当作一个起点,然后起点加上偏移量,访问速度慢,而且也没有体现出使用指针本来的用意。后一种方法与直接用数组名访问数组元素相同。
③、指针数组
指针数组是讲一个元素全部是指针的数组。
定义方法同普通数组:
数据类型 * 数组名[数组长度]
例:char * s[2];//定义一个含有2个指针元素的数组,元素指针指向char类型,属一般指针。
前面提到的指向多维数组的指针是这样定义的:数据类型 * 指针名[一维长度]
例:char (* s)[2];//注意这里的s是一个指针,而上例s是一个数组名,二者截然不同,指针可以实现自加运算,而数组名不能。
指针数组的典型应用是通过对字符数组赋初值而实现各维长度不一的多维数组定义。
例:char code season[4] = {“spring”,”summer”,”fall”,”winter”}
3、
指针与函数
①、指针变量作为函数的参数
指针变量作为函数的参数时,形势参数指针和实际参数指针二者进行的是值传递,直接把实参的值(注意:这个值是一个其它变量地址。)传给形参,传递的结果不会影响到实参的值。例pa实参原指向00H单元,传递后仍然指向00H单元,但函数执行后,00H单元里的内容(*pa)可能会发生变化。
②、返回指针数据的函数
返回指针数据的函数:某函数的返回值是一个指针。
定义方法:数据类型 * 函数名(形参)
例:int * x(char a)
③、函数形指针
函数形指针:一个指向函数入口地址的指针
函数形指针可代替函数名进行函数调用,通常是将一个函数作为参数传递给另一个函数。
定义方法:数据类型 (* 指针名)(形参)
例: int (* pfunc)();//定义一个指向返回值为整形的函数的指针
赋值方法:函数形指针变量名 = 函数名
引用方法:(* 指针名)(实参)或 指针名(实参)
④、函数指针数组
函数指针数组:定义一个数组,数组元素全部为函数形指针
例:code void (code * keyproctab[])() = {k0,k1,k2}
keyproctab :数组名
k0,k1,k2:已定义的函数名
第一个code表示数组的存储空间
void code 表示各数组元素的类型
引用方法:(* keyproctab[2])();//执行函数k2
以上这个例子就是汇编语言中常用的散转,数组下标,表示按键号,对应此下标的函数是键处理程序。
4、
指针与指针
①、指针形指针
指针形指针:指向另一个指针变量的指针,称多级指针。
定义:数据类型 **指针名
数据类型说明一个被指针形指针所指向的指针变量所指向的变量数据类型
例:int **p;
|