详解进阶指针(下)

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

函数指针

在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;
}

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

目录
相关文章
指针进阶(1)(下)
指针进阶(1)(下)
|
7月前
|
搜索推荐 C语言
详解指针进阶2
详解指针进阶2
|
存储
指针进阶详解!!!,干货满满(下)
指针进阶详解!!!,干货满满
|
存储 C++
指针进阶(纯干货!!!)
指针进阶(纯干货!!!)
41 0
|
搜索推荐
指针进阶(二)
指针进阶(二)
|
存储 C语言 C++
指针进阶(详解)
指针进阶(详解)
【C进阶】指针(二)
【C进阶】指针(二)
40 0
|
存储 编译器 C++
指针进阶详解!!!,干货满满(上)
指针进阶详解!!!,干货满满