指针数组,数组指针,函数指针、指针函数、函数指针数组

曾经的我是一个摆男,一言不合就开摆,直到我遇见了电子厂。。。。发生了一些不可描述的事,让我看清了社会的真相。。。 

进入正题!

分析时的两个步骤:是什么?怎么用?

是什么?

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个小时。睡觉! 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值