1、1:指针四要素(这部分主要从网上搜索到的,还不错): 指针的类型 指针所指向的类型 指针的值或者叫指针所指向的内存区 指针本身所占据的内存区 1 指针的类型。 从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就 是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的 类型: (1)int *ptr; /指针的类型是 int * (2)char *ptr; /指针的类型是 char * (3)int *ptr; /指针的类型是 int * (4)int (*ptr)3; /指针的类型是 int(*)3 (5)int *(*ptr)4; /指针的类型是 int *(
2、*)4 怎么样?找出指针的类型的方法是不是很简单? 1 .2 指针所指向的类型。 当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译 器将把那片内存区里的内容当做什么来看待。 从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符 *去掉,剩下的就是指针所指向的类型。例如: (1)int *ptr; /指针所指向的类型是 int (2)char *ptr; /指针所指向的的类型是 char (3)int *ptr; /指针所指向的的类型是 int * (4)int (*ptr)3; /指针所指向的的类型是 int()3 (5)int *(*ptr)4; /指针所指向
3、的的类型是 int *()4 在指针的算术运算中,指针所指向的类型有很大的作用。 指针的类型(即指针本身的类型 )和指针所指向的类型是两个概念。当你对 C 越 来越熟悉时,你会发现,把与指针搅和在一起的“类型“ 这个概念分成 “指针的 类型“和“指针所指向的类型“两个概念,是精通指针的关键点之一。 1.3 指针的值,或者叫指针所指向的内存区或地址。 指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是 一个一般的数值。在 32 位程序里,所有类型的指针的值都是一个 32 位整数,因为 32 位程序里内存地址全都是 32 位长。 指针所指向的内存区就是从指针的值所代表的那个内存地址
4、开始,长度为 si zeof(指针所指向的类型 )的一片内存区。以后,我们说一个指针的值是 XX,就相 当于说该指针指向了以 XX 为首地址的一片内存区域;我们说一个指针指向了某块 内存区域,就相当于说该指针的值是这块内存区域的首地址。 指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中 ,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区 是不存在的,或者说是无意义的。 以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的 类型是什么?该指针指向了哪里? 1.4 指针本身所占据的内存区。 指针本身占了多大的内存?你只要用函数 sizeof(指针
5、的类型 )测一下就知道 了。在 32 位平台里,指针本身占据了 4 个字节的长度。 指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。 (注释:在picc18 里,指针占用了两个字节) 下面就 picc18 列举个实例看下面程序 int data10=1,2,4,5,6,7,8; int lenth1,lenth2,lenth3; int *ptr1,*ptr2; main() ptr1= ptr2= lenth1=ptr2-ptr1; lenth2=(int)ptr2-(int)ptr1; lenth3=*ptr2-*ptr1; 在 watch 窗口可以看到 lenth1 为
6、 1,而 lenth2 为 2,可以这样解释:在 lenth1=ptr2-ptr1;这条语句中两个 INT 类型指针变量相减得一个(这在 c 中是允许的)非指针的数,这个数的代表如下: 如果这两个指针指向的内型为 INT 型,那么这个数代表两个指针之间相隔多少个 INT 型变量,显然在以上程序中,data0,和 data1之间相隔了 1 个 INT 型变量 而在 lenth2=(int)ptr2-(int)ptr1;实际上是求 data1和 data0之间占用多少个内存空间,注意(int)ptr 是 ptr 的值(不是 ptr 所指向的数的值) lenth3=*ptr2-*ptr1;相信稍微懂
7、 c 的人都知道是在求 ptr 所指向的两个值之间的差,和lenth3=data1-data0等效 大家不防试试 lenth4(char*)ptr2-(char*)ptr1;看看等于多少, 2: 指针函数和函数指针有什么区别 2.1,这两个概念都是简称,指针函数是指带指针的函数,即本质是一个函数。我们知道函数都又返回类型(如果不返回值,则为无值型) ,只不过指针函数返回类型是某一类型的指针。其定义格式如下所示: 返回类型标识符 *返回名称(形式参数表) 函数体 返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个
8、入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量” 。例如下面一个返回指针函数的例子: char data10; char* test(void); main() char *ptr; ptr=test(); char* test(void) char *p; p=data; return p; 注意:该程序在 picc18 中调试 2.2,“函数指针”是指向函数的指针变量,因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指
9、向函数。如前所述,C 在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。函数指针有两个用途:调用函数和做函数的参数。函数指针的说明方法为: 数据类型标志符 (*指针变量名) (参数) ;注:函数括号中的参数可有可无,视情况而定。下面的程序说明了函数指针调用函数的方法: char max(char x,char y); char min(char x,char y); char (*ptr)(char,char); char a=2,b=3,c; main() p
10、tr=max; c=(*ptr)(a,b); ptr=min; c=(*ptr)(a,b); char max(char x,char y) return x=y?x:y; char min(char x,char y) return xdatah =1; ptr1-datal =2; ptr2= ptr1-datah =3; ptr1-datal =4; ptr1-next=ptr2; ptr2-next=0; 数据 a,b 是一个结构型变量,ptr 则是指向结构型变量的指针,在 c 语言里,通过形如 ptr-x的形式来访问结构或者指针的成员。 在结构变量中定义了一个指针 struct da
11、tas *next; 这是在指针链中常用到的,ptr1-next=ptr2; ptr2-next=0;实际上已经建立了一条简单的指针链,当然建立指针链用这种初始化的方法不够简单,但是上面的程序只是为了说明指针和结构而已。 在单片机的 c 语言程序中,联合和结构是经常用在一起的下面在举一个简单的列子: typedef struct char datah; char datal; data; typedef union data twpbyte; int bytes; piccdata; piccdata adres10; piccdata *ptr1,*ptr2; char lenth1,len
12、th2; main() ptr2=adres; ptr1=adres; ptr1+; lenth1=ptr1-ptr2; lenth2=(char)ptr1-(char)ptr2; 在以上程序中,lenth2 为 2,而 lenth1 为 1,道理和第一个列子一样,只是应该注意的是在piccdata 型变量中占用的空间为 2 个字节而不是 4 个字节! 另:结构与联合是 pic 应用的一个好东西,这点 HOTpower 曾经有一很经典的文章,在此列中,只要稍微加以改动,就可以对一个 16 位变量即可以整体访问,也可分为高八位访问和低八位访问。这在 ad 转换中是很有用的。 4: const 与
13、指针 const 是一个 C 语言的关键字,它限定一个变量不允许被改变。 如果 const 关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况: int b = 500; const int* a = 1 int const *a = 2 Int* const a = 3 const int* const a = 4 如果 const 位于星号的左侧,则 const 就是用来修饰指针所指向的变量,即指针指向为常量;如果 const 位于星号的右侧,const 就是修饰指针本身,即指针本身是常量。因此,1和2的情况相同,都是指针所指向的内容为常量(const 放在变量声明符的位置无关) ,
14、这种情况下不允许对内容进行更改操作,如不能*a = 3 ;3为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如 a+是错误的;4为指针本身和指向的内容均为常量。 有了上面的基础,对于在 picc18 中的 c 语言应用就可以开始了,在单片机编程中,经常会用到查表程序等,通常把大量的数据放入 rom 中,下面是一个简单的列子 const int a8=1,2,3,-3,3,5,6,7; const int *ptr; main() ptr=a; ptr+; 显然 ptr 是一个指向常量的指针,ptr 指向的数是不可变的,但是 ptr 本身是可变的,我们可以通过 ptr 来访问定义在 rom 中的数组 a8;参考链接:http:/