详解进阶指针(下)

简介: 详解进阶指针(下)

函数指针

在C语言中,函数指针是指向函数的指针变量。它可以用来存储和访问函数的地址,从而可以通过函数指针调用相应的函数。

我们先来看一段代码:

#include <stdio.h>
void test()
{
 printf("hehe\n");
}
int main()
{
 printf("%p\n", test);
 printf("%p\n", &test);
 return 0;
}

两个都是test函数的地址,想要将test的地址保存到指针里,我们可以这样做:

void test()
{
  printf("hehe\n");
}
int main()
{
  printf("%p\n", test);
  printf("%p\n", &test);
  void (*pfun)() = test;
  printf("%p\n", pfun);
  return 0;
}

这样就成功的将test函数地址存到了指针中去。

利用函数指针数组实现简易计算器

相信大家都能够写出一个计算器,所以我们来用函数指针数组来实现一下。

#include<stdio.h>
int add(int a, int b)
{
  return a + b;
}
int sub(int a, int b)
{
  return a - b;
}
int mul(int a, int b)
{
  return a * b;
}
int div(int a, int b)
{
  return a / b;
}
int main()
{
  printf("*********************\n");
  printf("**1.add*******2.sub**\n");
  printf("**3.mul*******4.div**\n");
  printf("*******0.exit********\n");
  int x, y;
  int input = 1;
  int (*p[5])(int, int) = { 0,add,sub,mul,div };
  int ret = 0;
  do
  {
    printf("请选择操作:");
    scanf("%d", &input);
    if (0 < input && input < 5)
    {
      printf("请输入操作数:");
      scanf("%d %d", &x, &y);
      ret = (*p[input])(x, y);
      printf("%d\n", ret);
    }
    else if (input == 0)
    {
      printf("退出程序");
    }
    else
    {
      printf("输入有误,重新选择");
    }
  } while (input);
  return 0;
}

我们首先将加减乘除四个功能分别封装为四个函数,然后将四个函数的地址,存放到指针p中,为了更好的对应,我们把第一个元素设置为0,之后进入循环,将input作为操作数传参给p指针数组的下标,x和y作为操作数传参给对应的函数将返回值赋给ret,最后打印ret即可得到结果。

指针和数组题测试

我们了解了之后,来看一下我们掌握的怎么样

//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));// 16,数组名单独放到sizeof代表的是整个数组的大小,16个字节
printf("%d\n",sizeof(a+0));// 4/8 并非是单独放到sizeof中所以代表的是数组首元素的地址
printf("%d\n",sizeof(*a));//4,*a代表对首元素地址解引用,也就是1这个数字也就是4byte//*a == *(a+0) == a[0]
printf("%d\n",sizeof(a+1));// 4/8代表数组中第二个元素的地址
printf("%d\n",sizeof(a[1]));// 4代表数组中第二个元素
printf("%d\n",sizeof(&a));// 4/8 &a代表a数组的地址,地址的字节是4/8
printf("%d\n",sizeof(*&a));// 16 &a得到数组的地址,后解引用访问整个数组的大小,所以是16
printf("%d\n",sizeof(&a+1));//4/8 &a得到的是地址,+1还是地址所以是4/8
printf("%d\n",sizeof(&a[0]));//4/8 a[0]是首元素,&得到地址所以是4/8
printf("%d\n",sizeof(&a[0]+1));//4/8 得到地址后+1还是地址
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6 数组名arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节
printf("%d\n", sizeof(arr+0));//4/8 arr是首元素的地址==&arr[0],是地址就是4/8个字节
printf("%d\n", sizeof(*arr));//1 arr是首元素的地址,*arr就是首元素,大小就是1Byte
printf("%d\n", sizeof(arr[1]));//1 数组中第二个元素
printf("%d\n", sizeof(&arr));//4/8 整个数组的地址
printf("%d\n", sizeof(&arr+1));//4/8 整个数组地址+1
printf("%d\n", sizeof(&arr[0]+1));//4/8 数组第一个元素的地址+1,第二个元素的地址
printf("%d\n", strlen(arr));//随机值,arr是首元素的地址
printf("%d\n", strlen(arr+0));//随机值,arr是首元素的地址, arr+0还是首元素的地址
printf("%d\n", strlen(*arr));//err,arr是首元素的地址, *arr就是首元素 - 'a' - 97
printf("%d\n", strlen(arr[1]));//err, 'b' - 98
printf("%d\n", strlen(&arr));//随机值 地址
printf("%d\n", strlen(&arr+1));//随机值 地址
printf("%d\n", strlen(&arr[0]+1));//随机值 地址
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7 整个数组的大小包括'\0'
printf("%d\n", sizeof(arr+0));//4/8 首元素地址
printf("%d\n", sizeof(*arr));//1 访问数组首元素
printf("%d\n", sizeof(arr[1]));//1 数组中第二个元素
printf("%d\n", sizeof(&arr));//4/8 地址
printf("%d\n", sizeof(&arr+1));//4/8 地址
printf("%d\n", sizeof(&arr[0]+1));//4/8 地址
printf("%d\n", strlen(arr));//6 数组的长度,不包括'\0'
printf("%d\n", strlen(arr+0));//6 arr + 0 的类型是指向字符串的指针,strlen(arr + 0) 返回指针指向的字符串的长度,不包括终止符 \0
printf("%d\n", strlen(*arr));//err 
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen(&arr));//随机值 地址
printf("%d\n", strlen(&arr+1));//随机值 地址
printf("%d\n", strlen(&arr[0]+1));//随机值 地址
char *p = "abcdef";
printf("%d\n", sizeof(p));//4/8 地址
printf("%d\n", sizeof(p+1));//4/8 地址
printf("%d\n", sizeof(*p));//1 代表a
printf("%d\n", sizeof(p[0]));//1 代表a
printf("%d\n", sizeof(&p));//4/8 地址
printf("%d\n", sizeof(&p+1));//4/8 地址
printf("%d\n", sizeof(&p[0]+1));//4/8 地址
printf("%d\n", strlen(p));//随机值 地址
printf("%d\n", strlen(p+1));//随机值 地址
printf("%d\n", strlen(*p));//err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机值 地址
printf("%d\n", strlen(&p+1));//随机值 地址
printf("%d\n", strlen(&p[0]+1));//随机值 地址
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//48 整个数组的大小,4*12=48
printf("%d\n",sizeof(a[0][0]));//4 首行数组的首元素
printf("%d\n",sizeof(a[0]));//16 首行数组
printf("%d\n",sizeof(a[0]+1));//4/8 首行数组地址+1
printf("%d\n",sizeof(*(a[0]+1)));//4 第一行第二个元素解引用
printf("%d\n",sizeof(a+1));//4/8 未单独放代表地址,+1还是地址
printf("%d\n",sizeof(*(a+1)));//16 a+1是第二行的地址,*(a+1)就是第二行,计算的就是第二行的大小
printf("%d\n",sizeof(&a[0]+1));//4/8 地址
printf("%d\n",sizeof(*(&a[0]+1)));//16 第二行的大小
printf("%d\n",sizeof(*a));a表示数组首元素的地址,也就是第一行的地址 *a 就是第一行,也就相当于是第一行的数组名 *a--> *(a+0) -- a[0]
printf("%d\n",sizeof(a[3]));//16

总结

数组名的意义:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址

指针题测试

给大家留一个看起来很复杂的指针测试题,相信大家理解了指针后,一定能轻而易举的写出来

int main()
{
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
 printf("%s\n", **++cpp);
 printf("%s\n", *--*++cpp+3);
 printf("%s\n", *cpp[-2]+3);
 printf("%s\n", cpp[-1][-1]+1);
 return 0;
}

最后吸收一下大家的手气。

目录
相关文章
|
弹性计算 安全 Linux
阿里云服务器搭建宝塔面板(新手入门)
阿里云服务器搭建宝塔面板(新手入门)阿里云服务器网以CentOS操作系统为例,安装宝塔Linux面板,先远程连接到云服务器,然后执行宝塔面板安装命令,系统会自动安装宝塔面板,安装完成后会返回面板地址、账号和密码,然后在安全组开通宝塔面板端口号
784 0
|
网络协议 数据可视化 Java
衣带渐宽终不悔!嵌入式大牛10年调Bug经验总结
衣带渐宽终不悔!嵌入式大牛10年调Bug经验总结
131 0
|
运维 Prometheus 监控
产品动态丨阿里云计算巢月刊-2023年第04期
计算巢支持对服务实例的批量升级、全托管服务支持自定义运维项等7项功能更新;计算巢私有化部署接入Prometheus监控最佳实践;鸿翼医药智能RA平台、可道云网盘Kodbox及数据可视化开放平台datart等合作伙伴服务更新……让优秀的企业软件生于云、长于云~
产品动态丨阿里云计算巢月刊-2023年第04期
|
定位技术 iOS开发
iOS中 百度地图详解 韩俊强的博文
需要准备工作按照下图引进类库 需要添加 添加的两个字符串为:NSLocationWhenInUseUsageDescription  /  NSLocationAlwaysUsageDescription 默认定位设置: 设置工作准备完毕上代码: 指示根视图: ...
758 0
|
5天前
|
弹性计算 人工智能 安全
云上十五年——「弹性计算十五周年」系列客户故事(第二期)
阿里云弹性计算十五年深耕,以第九代ECS g9i实例引领算力革新。携手海尔三翼鸟、小鹏汽车、微帧科技等企业,实现性能跃升与成本优化,赋能AI、物联网、智能驾驶等前沿场景,共绘云端增长新图景。
|
11天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
2天前
|
云安全 人工智能 安全
Dify平台集成阿里云AI安全护栏,构建AI Runtime安全防线
阿里云 AI 安全护栏加入Dify平台,打造可信赖的 AI
|
10天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
5天前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
482 13