(一)数组指针
(二) 字符指针
(三)指针数组
(四)数组指针的其他替代方式
(五)实战练习
(六)数组参数和指针参数
(七)数组传参
(八)函数指针
(九)函数指针数组
(十)指向函数指针数组的指针
(十一)回调函数
(十二)快排函数
总述:指针类型纷繁复杂,但是相信苦心人天不负,一定可以掌握的!.
字符指针
char ch='w';
char*p=&ch;
常量字符串
char*p="ancdef";
指针数组
int* p[10];
char* ch[5]
数组指针
int *p3;整形指针
char* p4;
int arr[5]
int (*p3)[5]=&arr;(去掉名字之后就是类型 int(*)[5])
函数指针:
int* (*padd)[10]=&arr;
函数指针的数组
int(*pa[5])(int,int);
指向函数指针数组的指针
int(*(*ppa)[5]))(int,int)=&pa;
(一)数组指针(存放数组的地址)
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int (*p)[10]=&arr;// &arr指取得是arr的地址
(*p)表示指针变量
[]的优先级高于*
指针p指向一个数组有十个元素
int i=0;
for(i=0;i<10;i++)
{
printf("%d",(*p)[i]);
}
return 0;
}
int main()
{
char* arr[5];
char* (*pa)[5]=&arr; //
(*pa) Pa是个指针变量名 *说明整体是指针
[5] 指pa指向的数组为5个元素
char* 指pa指向的数组的元素类型是char*
}
使用:*pa==arr
int main()
{
int arr={1,2,3,4,5,6,7,8,9,10};
int (*pa)[10]=&arr;
int i=0;
for(i=0;i<10;i++)
{
(*pa)[i]; (*pa拿到数组的地址,对i赋值得到每个值)
}
}
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=a;
int i=0;
for(i=0;i<10;i++)
printf("%d",*(p+i));
}
(二)字符指针
int main()
{
char a='w';
char* pc=&a;// pc字符指针类型char*
}
{
char arr[]="abcdef";
char* pc=arr;//arr为首元素地址,字符指针存放数组名,也就是把首元素a的地址放到pc里。
printf("%s",pc);
printf("%s",arr);
}
{
char*p="abcdef" (""为常量字符串,实际上是把a的地址赋给p)
printf("%c",*p);
printf("%s",p);(从p存的地址处出发开始打印一个字符串)*/}
{
char a1[]="abcdef";
char a2[]="acbdef";(a1和a2是俩块不同的内存单元)
(a1!=a2) {a1和a2分别为数组首元素地址,自然不同}
char*p1="abcdef"
char*p2="abcdef"(俩个字符串一模一样,常量字符串不可修改,在内存中不能存俩份,所以相同)
(a1==a2)
}
(三)指针数组
int main()
{
int* a[10]={0}; 存放整形指针的数组 称为整形指针数组
char* pch[10]; 存放字符指针的数组
int a=10; int b=20; int c=30; int d=40;
int* arr={&a,&b,&c,&d} arr[i]是每个元素的地址
int i=0;
for(i=0;i<4;i++)
{
*(arr[i]);
}
}
int main()
{
int a1={1,2,3,4,5};
int a2={2,3,4,5,6};
int a3={3,4,5,6,7};
int* prr[]={a1,a2,a3};存入首元素地址
for(i=0;i<3;i++)
{int j=0;
for(j=0;j<5;j++)
{
*(prr[i]+j);
}
}
(四)数组指针的其他替代方式
int main()
{
int arr[3][5]={
{1,2,3,4,5},{2,3,4,5,6},{4,5,6,7,8}};
print1(arr,3,5);
print2(arr,3,5);
}
void print1(int arr[3][5],int x,int y)
{
int i=0;
int j=0;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
{printf("%d",arr[i][j]);
}
printf("\n");}/*main中写数组名,传参的列表写为数组形式
把二维数组想像为一维数组再去讨论首元素地址,每行为一个元素,则arr有三个元素。即arr代表
第一行的地址 */
}
void print2(int(*p)[5],int x,int y)//参数为数组指针
{
int i=0;
for(i=0;i<x;i++)
{
int j=0;
for(j=0;j<y;j++)
*(p+i);//找到这一行
*(*(p+i)+j)//找到这一行第j个元素
}
}
/*a[i]==*(a+i)==*(p+i) ==p[i] p与arr可以互换
[j]==*(a+j)*/
(五)实战练习
int main()
{
int a[5];
int *pa[10];//指针数组 类型int*
int (*pa)[10];//数组指针 该指针指向一个数组 数组十个元素 每个元素类型int
int (*pa[10])[3]/*该指针数组pa[10]有三个元素
每个元素是一个数组指针,
该数组指针指向的数组有10个元素,每个元素int */}
(六) 数组参数和指针参数
一维数组传参
int a[10];
void canshu(int a[]);
void canshu(int a[10]);
void canshu(int*arr);数组名为首元素地址,每个首元素的地址都是int型的
int* arr2[10];
void canshu(int*arr[40]);
void canshu(int**arr);一级指针的地址放在二级指针中
首元素为第一行的地址 不能传int*arr 因为它非整型
int a[3][5];
int (*a)[5]
一级指针传参
int arr[10]={1,2,3,4,5};
int *p=arr;
void can(int *p)
//思考:当一个函数的参数为一级指针的时候,函数可以接受什么样参数
void can1(int *pa)
void can2(char*pa)
{ int a=10;
int*p1=&a;
can(p1);
can(&a);
}
// 二级指针传参
void can(int **p)
int n=10;
int*p=&n;
int**pp=&p;
can(pp);
can(*p);
int* arr[10];
can(arr); //指针数组传参也可以
(七) 数组传参
一维数组传参
int a[10];
void canshu(int a[]);
void canshu(int a[10]);
void canshu(int*arr);数组名为首元素地址,每个首元素的地址都是int型的
int* arr2[10];
void canshu(int*arr[40]);
void canshu(int**arr);一级指针的地址放在二级指针中
二维数组传参的时候行可以省略,列不能省略
且首元素为第一行的地址 不能传int*arr 因为它非整型
int a[3][5];
int (*a)[5]
一级指针传参
int arr[10]={1,2,3,4,5};
int *p=arr;
void can(int *p)
思考:当一个函数的参数为一级指针的时候,函数可以接受什么样参数
void can1(int *pa)
void can2(char*pa)
{ int a=10;
int*p1=&a;
can1(p1);
can1(&a);
char ch='w';
char*pc=&ch;
can2(pc);
can2(&ch);
}
二级指针传参
void can(int **p)
int n=10;
int*p=&n;
int**pp=&p;
can(pp);
can(*p);
或:
int* arr[10];
can(arr); 指针数组传参也可以
(八) 函数指针(指向函数的指针) &函数名==函数名 都是函数的地址
int (*pa)(int,int)=add;
(*pa) (2,3)找到函数地址后调用,然后往里面传参
void print(char*str)
{
printf("%s",str);
}
int main()
{
void(*p)(char*)=print;
(*p)(woaini);
}
(* (void(*)()) 0) () 0强制转换为void(*)()后解引用调用
void ( *signal( int , void(*)(int)) ) (int);
函数名 signal 参数有2个,一个是int,一个是函数指针
函数返回类型void(*) (int)
typedef void(*mama)(int);给函数返回类型重新取个名字
则上面的可以写成 mama signal(int,mama);
(九)函数指针数组
有一个数组可以存放多个函数的地址---存放函数指针的数组
int(*pa[4]) (int,int)={Add,sub,mul,dlv};
pa先与[]结合说明是数组,类型为int(*)(int,int) ;
for(i=0;i<4;i++)
{
pa[i](2,3);
}
例:char*strcpy(char*a,const char*b);
写一个函数指针pf,指向strcpy
char* (*pf)(char*a,const char*b);
写一个函数指针数组
char* (*pf[4]) (char*a,const char*b);
(十)指向 函数指针数组 的指针
int main()
{
int arr={0};
int (*p)[10]=&arr;
int (*parr[4])(int,int); parr是数组,函数指针的数组
int(*(*pp)[4]) (int,int)=&parr; pp是一个数组指针,指向一个数组
每个元素的类型是函数指针,元素类型int(*)(int,int)
}
(十一)回调函数(通过一个函数指针调用的函数 把函数的地址作为参数传递给另一个函数,
当这个指针被用来指向所调用的函数时称为回调)
void text(void(*p)(char*))
{
printf("text\n");
p("bit");
}
void print(char*str)
{
printf("hehe%s",str);
}
int main()
{
text(print);
}
(十二)快排函数
qsort:可以排序任意数组--库函数
算法为quick sort
void*类型的指针 可以接受任意类型的地址 (垃圾桶)
不能进行解引用操作 也不能进行加减整数的操作
return *(int*)e1-*(int*)e2;
若e1>e2返回一个大于0的数字
传参:base(start of target array)
num(array size in elements)
width(每个元素多少字节)
compare function(比较函数,把俩个函数比较的方法写成一个函数传进去,
,比较俩个)
elemt 1()要比较的那俩个元素的地址
elemt 2()
void qsort(void*base,size_t num,size_width,int(*cmp)(const void*e1,const void*e2))
int cmp(const void*e1,const void*e2)
{
}