1指针的声明
int *a;
int* a;
int* a,b,c //注 *号是*a的一部分,只对标识符有用,所以b和c只是整形变量
int *a,*b,*c;
//也可以指定初始值
char *msg = “hello world”; == char *msg; msg = “hello world”;
注意:hello world看起来是赋值给 *msg的,其实是赋值给 msg 的
2 间接访问操作符
指通过指针访问它指向的地址的操作,也叫解引用指针。
int a = 10;
int *b = &a;
printf(*b);
a是一个整形变量,b是一个指针变量,b指向a地址,当使用*b时,访问的是b所指向的地址内存储的数据,也就是a,所以*b=10。
3初始化和非法指针
int *a;
*a=12;
创建了一个名为a的指针变量,然后把12放到a的地址中。
注意:我们并没有初始化指针a,所以我们不知道a所指向的地址,如果变量是静态的,那么a会指向0,如果变量是自动的,根本不会被初始化,a为一个非法地址。这样的做法是错误。
4 NULL指针
null指针式一个特殊指针,它并不指向任何值。对一个NULL指针进行引用操作是非法的。
5 指针的指针
int a = 12;
int *b = &a;
int **c = &b;
b表示指向a的指针,**c可以表示为*(*c),*c表示b指针的值,就是a的地址,**c表示的就是a的地址的值,就是12。
6 实例
求字符串的长度。
int strlen1(char *str){
int len = 0;
while(*(str++) != '\0'){
len++;
}
return len;
}
查找字符
int find_char1(char *str,char c){
while(*(str++) != '\0'){
if(c==*str){
return 1;
}
}
return 0;
}
7 指针运算
当一个指针跟一个整数进行算术运算时,整数会根据指针类型进行动态调整。比如:
float *a = 3.14;
a = a + 1; //float占4个字节,a+1的时候,会根据字节长度,调整为 1*4实际上就是,
// a+4
所以,char类型的指针加1,就是指向下一个char,而float类型,就指向下一个float。
注意:指针的运算仅限于加减两种。
8函数指针
1. 初始化函数指针
int f(int);
int *(pf)(int) = &f; // int *(pf)(int) = f;
这里声明了一个函数指针,*pf(int)通过赋值初始化,在函数指针初始化的时候,函数原型很重要,因为编译器要检查函数指针的类型。
&操作符不重要,int *(pf)(int) = f; 编译器在编译的时候会自动加上&符号。
可以这么调用
int a = f(25);
int b = *(pf)(25)
int c = pf(25);
第一行的执行过程是,函数名首先会转换为一个函数指针,指向的是函数在内存中的位置。
第二行的操作是,先通过指针pf取出函数名,再通过函数名执行第一行的过程,所以这么写是没必要的。
第三行直接通过函数指针进行调用。
2. 回调函数
函数指针可以作为回调函数参数,传递到函数中。