指针的进阶【中篇】

简介: 指针的进阶【中篇】

📀4.数组参数

💿4.1.一维数组传参

🌰请看代码👇

#include<stdio.h>
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int* arr)//ok
{}
void test2(int* arr2[20])//ok
{}
void test2(int **arr2)//ok
{}
int main()
{
  int arr[10] = { 0 };
  int* arr2[20] = { 0 };
  test(arr);
  test2(arr2);
  return 0;
} 

💡一维数组传参的时候,形参可以是数组,也可以是指针

💡当参数是指针的时候,要注意类型


💿4.2.二维数组传参

🌰请看代码👇

void test(int arr[3][5])//ok
{}
void test(int arr[][])//NO
{}
void test(int arr[][5])//ok
{}
//二维数组传参,函数形参的设计只能省略第一个[]的数字
//因为对一个二维数组。可以不知道有多少行,但是必须知道一行有多少个元素
void test(int *arr)//NO
{}
void test(int* arr[5])//NO
{}
void test(int (*arr)[5])//ok
{}
void test(int **arr)//NO
{}
int main()
{
  int arr[3][5] = { 0 };
  test(arr);
  return 0;
}

💡二维数组传参,参数可以是指针,也可以是数组

💡如果是数组,行可以省略,但是列不能省略

💡如果是指针,传过去的是第一行的地址,形参就应该是数组指针


📀5.指针参数

💿5.1.一级指针传参

🌰请看代码👇

void print(int* p, int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d\n", *(p + 1));
  }
}
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int* p = arr;
  int sz = sizeof(arr) / sizeof(arr[0]);
  //一级指针p,传给函数
  printf("%d\n", sz); 
  print(p, sz);
  return 0;
}

💡当函数的参数部分是一级指针的时候,可以接收什么参数?

👉 int a;
print (&a,10);
👉 int * p1= &a;
print (p1,10);
👉int arr[10];
print (arr,10);


💿5.2.二级指针传参

🌰请看代码👇

void test(int** ptr)
{
  printf("%d\n", **ptr);
}
int main()
{
  int n = 10;
  int* p = &n;
  int **pp = &p;
  test(pp);
  test(&p);
  return 0;
}

💡当函数的参数部分是二级指针的时候,可以接收什么参数?

👉 test (二级指针变量);
👉 test (一级指针变量的地址);
👉 int * arr[10];
👉 test (arr);


📀6.函数指针

👉类比一下:

整型指针 ---- 指向整型的指针 ---- int *

字符指针 ---- 指向字符的指针 ---- char *

数组指针 ---- 指向数组的指针 ---- int arr[10]; int (*p)[10] = &arr;

函数指针 ---- 指向函数的指针 ---- int (*pf)(int, int) = Add;


💡函数名 和 &函数名 都是函数的地址,没有区别👇

int main()
{
  printf("%p\n", &Add);
  printf("%p\n", Add);
  return 0;

834cbc93a2fa473780471ea2f4331f1f.png

🌰请看代码👇

int Add(int x, int y)
{
  return x + y;
}
// &函数名得到的就是函数的地址
int main()
{
  //printf("%p\n", &Add);
  //printf("%p\n", Add);
  int (*pf)(int, int) = Add;//函数的地址要存起来,就要放在 函数指针变量 中
  // pf就是函数指针
  //int ret = (*pf)(3, 5); 这里的*没什么用,就是摆设
  //int ret = Add(3, 5);
  int ret = pf(3, 5);
  printf("%d\n", ret);
  return 0;
}

c5cb3ddaf2ac455a824aa7d32de9b395.png

🌰再举个栗子,请看代码👇

char* test(int c, float* pf)
{
}
int main()
{
  char* (*pt)(int, float*) = test;
  return 0;
}

🥰希望烙铁们能够理解🥰


💿6.1. 代码1

看代码和注释👇

int main()
{
  (*( void (*)() ) 0)();// 这是一次函数调用
  //1.将0强制类型转换成 void(*)()类型的函数指针
  //2.这就意味着0地址处放着一个函数,函数没参数,返回类型是 void
  //3.调用0地址处的这个函数
  return 0;
} 

💿6.2. 代码2

int main()
{
  void (* signal(int, void(*)(int) ) )(int);// 是一个函数的声明
  //函数的名字是 signal
  //signal函数的参数第一个是int类型,第二个是void(*)(int)类型的函数指针
  //该函数指针指向的函数参数是int,返回类型是void
  // 
  //signal函数的返回类型也是一个函数指针
  //该函数指针指向的函数参数是int,返回类型是void
  return 0;
}

📀7.函数指针数组

💡数组的每个元素是一个函数指针

🌰请看代码👇

int Add(int x, int y)
{
  return x + y;
}
int Sub(int x, int y)
{
  return x - y;
}
int Mul(int x, int y)
{
  return x * y;
}
int Div(int x, int y)
{
  return x / y;
}
int main()
{ 
  //存放函数指针的数组 ---- 函数指针数组
  int(*pf[4])(int, int) = { Add,Sub,Mul,Div };
  int i = 0;
  for (i = 0; i < 4; i++)
  {
    int ret = pf[i](8, 4);
    printf("%d\n", ret);
  }
  return 0;
}

c3d3dd8f09874d7199597a993e2f323d.png

🌰在此基础上我们可以写一个简单的计算器👇

int Add(int x, int y)
{
  return x + y;
}
int Sub(int x, int y)
{
  return x - y;
}
int Mul(int x, int y)
{
  return x * y;
}
int Div(int x, int y)
{
  return x / y;
}
void menu()
{
  printf("****************************************\n");
  printf("******    1.add        2.sub     *******\n");
  printf("******    3.mul        4.div     *******\n");
  printf("******          5.exit           *******\n");
  printf("****************************************\n");
}
int main()
{
  int input = 0;
  int x = 0;
  int y = 0;
  int ret = 0;
  //转移表
  int (*pf_Arr[5])(int, int) = {NULL,Add,Sub,Mul,Div};
  do                         // 0  1   2   3   4
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    if (input == 0)
    {
      printf("退出计算器\n");
      break;
    }
    else if (input >= 1 && input <= 4)
    {
      printf("请输入两个操作数:>");
      scanf("%d %d", &x, &y);
      ret = pf_Arr[input](x, y);
      printf("%d\n", ret);
    }
    else
    {
      printf("选择错误\n");
      break;
    }
  } while (input);
  return 0;
}

a140ba8d7deb46299ff176bdb37064b9.png

目录
相关文章
|
5月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
5月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
5月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
5月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
5月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
5月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
47 4
|
5月前
指针进阶(3)
指针进阶(3)
41 1
|
5月前
|
C++
指针进阶(1)
指针进阶(1)
43 1
|
5月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
42 2
|
5月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
49 0