1.指针数组和数组指针
(1)指针数组:一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量,定义如下:
int *p[4];
解析:由于[]比*优先级高,因此p先与[4]结合,形成p[4]形式,这里显然是数组形式,表示P数组有4个元素。然后再与p前面的*结合,“*”表示此数组是指针类型的,每个数组元素(相当于一个指针变量),都可指向一个整型变量。
指针数组比较适合用来指向若干字符串,使字符串处理更加方便灵活。
(2)数组指针:指指向数组的一个指针,它起始还是一个指针,只不过是指向数组而已。
int (*p)[4];
解析:由于[]的优先级高于*,所以需要写成(*p)。
2.指向函数的指针 (以下简称指针函数)
如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址(又称为入口地址)称为这个函数的指针。
eg:int (*p)(int,int);
定义p是一个指向函数的指针变量,它可以指向函数类型为整型且有两个整型参数的函数。p的类型用int(*)(int,int)表示。
怎么定义和使用指向函数的指针:
类型名 (* 指针变量名)(函数的参数列表)
使用指针函数的注意事项:
1)定义指向函数的指针变量,并不意着这个指针变量可以指向任何函数,它只能指向在定义时指定的类型的函数。
2)如果用指针调用函数,必须先用指针变量指向该函数。如:p = max; 这就把max函数的入口地址赋给了指针变量p。
3)用函数指针调用函数时,只需要用(*p)代替函数名即可,如:c = (*p)(a,b)
4)对指向函数的指针变量,不能进行算术运算,如:p +n,p++等。
3.用指针处理链表
建立一个简单的链表:
1 #include<stdio.h> 2 struct Student 3 { 4 int num; 5 float score; 6 struct Student *next; 7 }; 8 int main() 9 { 10 struct Student a,b,c,*head,*p; 11 a.num = 10101; 12 a.score= 89.5; 13 b.num = 10103; 14 b.score = 90; 15 c.num = 10107; 16 c.score = 85; 17 head = &a; 18 a.next = &b; 19 b.next = &c; 20 c.next = NULL; 21 p = head; 22 do 23 { 24 print("%d%5.1f ",p->num,p->score); 25 p = p->next; 26 }while(p!= NULL) 27 return 0; 28 }
链表是一种常见的重要的数据结构。他是动态的进行存储分配的一种结构。
链表简介:链表有一个“头指针”变量,图中以head表示,它存放一个地址,该地址指向一个元素。链表中每一个元素称为“结点”。每个节点都应该包含两部分(1)用户要用到的实际数据;(2)下一个结点的地址。可以看出,head指向第一个元素,第一个元素又指向第二个元素......直到最后一个元素,该元素不再指向其他元素,它称为表尾,它的地址部分放一个“NULL”,(表示空地址),链表到此结束。
链表中各元素在内存中的地址是不连续的,要找某一元素,必须先找到上一元素,根据它提供的下一元素地址才能找到下以元素。如果不提供“head”头指针,则整个链表都无法访问。
3.定义指针变量时的注意事项
(1)指针变量前的“*”表示该变量的类型为指针变量。指针变量名pointer_1和pointr_2。不能写成*pointer_1和*pointer_2;不能写成“*pointer_1 = &a;”,因为a的地址是赋给指针变量pointer_1,而不是赋给*pointer_1。
(2)int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};
从二维数组的角度来看,a代表二维数组首元素的地址,现在的首元素不是一个简单的整型元素,而是由四个整型元素组成的一位数组。因为a代表的是首行的首地址,a+1代表的是序号为1的行的首地址。