从指针的基本概念可以理解,在计算机中,数据是存储在计算机的存储单元中,每个存储单元都有一个编号,指针就是对应着存储单元的编号,根据指针就可以找到数据存储的地址。
1 指针的类型
指针的类型是指针本身所具有的类型,一般去掉指针变量名,就是指针的类型。
int*p;//指针的类型是int*
char*p;//指针的类型是char*
int(*p)[3];//指针的类型是int(*)[3]
指针所指向的类型是指指针所指向的变量的数据类型,把*和指针变量名都去掉后,留下的就是指针所指向的类型。
int*p; //指针所指向的类型是int
char*p; //指针所指向的的类型是char
int**p; //指针所指向的的类型是int*
int(*p)[3]; //指针所指向的的类型是int()[3]
int*(*p)[3]; //指针所指向的的类型是int*()[3]
2 指针的赋值与运算
2.1 初始化与赋值
指针定义的方式:类型说明符 * 指针变量名
赋值方式有两种:
(1)初始化时进行赋值:
int a=1;
int *p=&a;
(2)先定义后赋值
int a=1;
int *p;
p=&a;
2.2 指针的运算
取地址运算符:&
取内容运算符:*
例如:
main(){
int a=5,*p=&a;
printf ("%d",*p);
}
上述将int型变量a的地址给了指针p,对p取内容为a的值5,输出结果为5
指针自身可以加一个数或者减一个数,代表指针向前或向后移动了n个位置,例如指针p的运算:p++,p–,p+n
两个指针之间只能进行减运算,表示两个地址之间的位移量,加法和其他运算对于其没有任何意义。
3 数组与指针变量
数组的内存单元一般是连续的,一个数组的数组名就是一个指针变量。指针可以指向一个数组,也可以指向一个数组中的某个元素。
3.1 一维数组与指针变量
一维数组定义后赋值给指针变量,可以用两种方法来访问数组元素。
一种称为下标法,即用“数组名[i]”的形式访问数组元素
一种称为指针法,即采用*(指针名+i)形式,用间接访问的方法来访问数组元素
例如:
int a[5]=[1,2,3,4,5],*p;
p=a;
printf ("%d",a[1])//使用第一种方法
printf ("%d",*(p+1))//使用第二种方法
3.2 二维数组与指针变量
C语言允许把一个二维数组分解为多个一维数组来处理。例如数组a[3][4]可分解为三个一维数组,即a[0],a[1],a[2]。
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
p = a;
在上述的二位数组赋值中,
对于数组的引用: p+i指向一维数组a[i]
对于数组元素的引用: *(p+i)+j指向二维数组i行j 列的元素的地址,*(*(p+i)+j)指向i行j列元素的值
for(i=0;i<3;i++)
for(j=0;j<4;j++) printf("%d ",*(*(p+i)+j));
4 结构体与指针变量
对结构体的指针变量,赋值与普通赋值一样,指针变量一般指向第一个成员变量
struct mystr
{
int a;
int b;
int c;
};
struct mystr ms={10,20,30};
struct mystr *p=&ms;
指针访问结构体成员变量的方式有两种:
第一种:使用指向运算符,p->a(一般都使用第一种)
第二种:使用.的方式,(*p).a
使用指针p访问结构体三个变量的下述方法一般是不太正规的,因为成员变量a和b之间可能会有若干个填充字节,在通过*p访问到成员变量a时,*(p+1)不一定正好访问到b,但是也有可能访问到。
*p; //访问成员a
*(p+1); //访问成员b
*(p+2) //访问成员c
5 函数与指针变量
在C语言中,一个函数会占用一段连续的内存区,函数名是函数所占内存区的首地址,把函数的首地址赋予一个指针变量,该指针变量指向该函数,这种指针变量被称为函数指针变量。
函数指针变量声明方式:类型说明符 (*指针变量名)();
“类型说明符”指函数返回值的类型,“(* 指针变量名)”表示“*”后面的变量是定义的指针变量,空括号表示指针变量所指的是一个函数。
例如:int (*p)();
int max(int a,int b){
if(a>b)return a;
else return b;
}
main(){
int max(int a,int b);
int(*pmax)();
int x=1,y=2,z;
pmax=max;
z=(*pmax)(x,y);
printf("%d",z);
}