曾经的我是一个摆男,一言不合就开摆,直到我遇见了电子厂。。。。发生了一些不可描述的事,让我看清了社会的真相。。。
进入正题!
分析时的两个步骤:是什么?怎么用?
是什么?
1、指针数组:本质是数组,数组中存储的每个元素是指针
怎么用?
以遍历数值指针数组为例,int* arr[4] = { &num1,&num2,&num3,&num4 };就是数值指针数组
void t1()
{
int num1 = 10;
int num2 = 20;
int num3 = 30;
int num4 = 40;
int* arr[4] = { &num1,&num2,&num3,&num4 };
int n = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0;i < n;i++)
{
printf("%3d", *arr[i]);
}
printf("\n");
}
int main(int argc,char *argv[])
{
t1();
return 0;
}
输出的时候为:*arr[i] 因为*()等价于[],所以也可以写成:**(arr + i)
这里讲一下:&arr[i] == (arr + i) 然后*arr[i] == **(arr + i)
不要搞混了
以遍历字符串指针数组为例,int* arr[4] = { "tienan","nuoshou","wanhao","jianmo" };就是字符串指针数组
#include <stdio.h>
void t2()
{
char *arr[4] = {"tienan","nuoshou","wanhao","jianmo",};
char* brr[4] = { "铁男","诺手","腕豪","剑魔" };
int n = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0;i < n;i++)
{
printf("%10s", arr[i]);
//printf("%10s",*(arr + i));//选一种输出即可
}
printf("\n");
for (i = 0;i < n;i++)
{
printf("%10s", brr[i]);
}
printf("\n");
//想把tienan的e打印出来怎么办?/***************难点******************/
//第一种,数组的方式
printf("%10c\n",*(arr[0] + 2));
//解析:arr[0]是“tienan”这个首元素的首字母地址,直接指向t,+2之后指向e,把e的打出来取*
//第二种,指针的方式
printf("%10c\n",*(*arr + 2));
//解析:arr是数组首元素地址,指向第一个元素,也就是”tienan“,*arr是取到第一个元素的第一个字母内容,也就是t,也就是*arr 和arr[0]等价,再+2之后指向e,把e打印出来再取*
//思考:下面这个输出什么?
printf("%10c\n",**arr + 2);
printf("\n");
}
int main(int argc,char *argv[])
{
t2();
return 0;
}
输出的时候为:arr[i]
因为字符串输出的时候是给首地址,所以输出少一个 *
为什么输出的是v? 因为*arr是取到 t 嘛,再取 * 是把它打印出来,**arr + 2就是打印 t 后面ASCII码值 +2 的字母。
arr是数组的首元素地址,&arr是数组的首地址,它们两个表示的地址相同,但是概念不同。对首地址取 * ,得到数组首元素地址。也就是说 *&arr 和 arr 等价。所以,对首地址 +1 ,偏移一个数组;对首元素 +1 ,偏移一个元素,对 *(首元素) +1 ,偏移一个字母。BUT!!对于数组指针来说,数组名只代表第0行的行地址(有些人说是第一行,无所谓,就是最开始的那一行),接下来要讲的是数组指针
继续!
2、数组指针:本质是指针,指向一个数组,指针的值是数组的地址
以数组指针遍历数值数组元素为例
#include <stdio.h>
void t3()
{
int arr[2][3] = {1,2,3,4,5,6};
int (*p)[3] = arr;
//写成int (*p)[3] = &arr;也行,但是要报警告
//写成int (*p)[3] = NULL;p = arr也行,这个不报警告
//下面输出0行1列元素,也就是2,两种方式可任选一种
printf("arr[0][1] = %d\n",*(*(p + 0) + 1));//*(*(p+0) + 1) == *(arr[0] + 1) == arr[0][1]
//printf("arr[0][1] = %d\n",arr[0][1]);//这种是数组的方式
//下面看+1后偏移多少
printf("arr[0][0] = %d\n",**p);
printf("arr[a][b] = %d\n",*(*(p+0)+0) + 1);//(**p + 1)
printf("arr[c][d] = %d\n",**(p + 1));
printf("arr[e][f] = %d\n",*(*p + 1));
//下面看指向的地址
printf("%p\n",**p);
printf("%p\n",**p + 1);
printf("%p\n",**(p + 1));
printf("%p\n",*(*p + 1));
//下面是数组指针遍历数组元素
int i,j;
for(i = 0;i < 2;i++)
{
for(j = 0;j < 3;j++)
{
printf("%3d",*(*(p + i) + j));
//printf("%3d",arr[i][j]);
}
}
printf("\n");
//也可以用这种方式连续输出
for(i = 0;i < 6;i++)
{
printf("%3d",*(*p + i));
}
printf("\n");
}
int main(int argc, char *argv[])
{
t3();
return 0;
}
继续!
3、函数指针:本质是指针,指向一个函数,指针的值是函数的地址
以下是函数指针普通用法
#include <stdio.h>
int fun_jia(int a,int b)
{
return a+b;
}
void t4()
{
int (*p)(int,int) = fun_jia;
//写成int (*p)(int a,int b)也行
//写成int (*p)(int x,int y) = &fun_jia;也行
//写成int (*p)(int x,int y) = fun_jia;也行
//写成int (*p)(int,int) = NULL;p = fun_jia;也行
printf("%d\n",fun_jia(1,2));
//输出的fun_jia(1,2)不能取地址!
}
int main(int argc, char *argv[])
{
t4();
return 0;
}
以下是函数指针进阶用法
#include <stdio.h>
int fun_jia(int a,int b)
{
int c = a + b;
return c;
//或者直接写成return a + b;
}
int fun_jian(int a,int b)
{
return a - b;
}
//新定义一个函数,用函数指针调用上面定义的函数
int func(int a,int b,int(*p)(int,int))
{
return p(a,b);
}
void t4()
{
printf("%2d\n",func(1,2,fun_jia));
printf("%2d\n",func(1,2,fun_jian));
}
int main(int argc, char *argv[])
{
t4();
return 0;
}
注意:上面我没写函数申明,但依然没有问题。是因为主函数在最下面。
继续!
4、指针函数:本质是函数,函数的返回值是指针。
#include <stdio.h>
#include <stdlib.h>//malloc要用
#include <string.h>//memset要用
int *fun_jia(int a,int b);
int *fun_jia(int a,int b)
{
int *p = (int *)malloc(sizeof(int));//在堆区申请空间,但不自动清0
if(p == NULL)//预防空间申请失败,堆区满了就可能失败
{
return 0;//如果没有这个判断语句,如果p == NULL,就会报错
}
memset(p,0,sizeof(int));//手动清0
*p = a + b;
return p;
free(p);//释放堆区空间,不想用了就释放
}
void t5()
{
int *p = fun_jia(1,2);
//int *p = NULL;
//p = fun_jia(1,2);
//写成int *p = fun_jia(1,2);也行
printf("%d\n",*p);
}
int main(int argc, char *argv[])
{
t5();
return 0;
}
继续!
5、函数指针数组:本质是数组,每个元素是函数地址,指针指向一个函数,指针的值是函数的地址,相当于函数指针int(*p)(int,int) = fun_jia;组合成数组的形式!而函数指针数组指针(指向函数指针数组的指针),它的每个元素是函数指针。别搞混了。。。
#include <stdio.h>
int fun_jia(int a,int b);
int fun_jian(int a,int b);
int fun_jia(int a,int b)
{
return a+b;
}
int fun_jian(int a,int b)
{
return a-b;
}
void t6()
{
int (*p[2])(int,int) = {fun_jia,fun_jian};//定义函数指针数组
//数组肯定要遍历嘛
int i;
for(i = 0;i < 2;i++)
{
printf("%3d",p[i](1,2));
}
printf("\n");
}
int main(int argc, char *argv[])
{
t6();
return 0;
}
这里输入写成:int (*p[2])(int,int) = {&fun_jia,&fun_jian}; 也行。
这里输出写成:printf("%3d",(*(p + i))(1,2)); 也行。
难吗,不难!只写了4个小时。睡觉!