目录

C语言数组指针变量函数指针变量

(C语言)《数组指针变量》《函数指针变量》

一. 数组 指针

指针数组:存放指针的数组 那数组指针是什么?
1 定义与基本概念

数组指针变量是指向数组的指针变量,其本质是一个指向数组首地址的指针。数组名本身即为数组首地址,因此数组指针变量可以直接通过数组名或指针运算符访问数组元素。 想要更加容易理解数组指针,可以类比字符/数组指针 类比: 字符指针—— 指向字符,储存字符的地址 整形指针——指向整形,储存整形的地址 数组指针—— 指向数组,储存数组的地址 例如:int arr[10]={0} 那么数组arr的地址就是 &arr

&加数组名 就是 数组的地址

2 声明与初始化

int arr[3] = {10, 20, 30}; // 普通数组 int (*p)[3] = &arr // 数组指针初始化 https://i-blog.csdnimg.cn/direct/f66530158dd0498ab7dfe950d05300e8.png

3 访问元素
  • *(p + i):访问第i个数组元素。
  • *(p + i) = value:给第i个数组元素赋值。
  • *(p + i)[j]:访问二维数组的第i行第j列元素。 int arr[3] = {10, 20, 30}; // 普通数组 int (*p)[3] = &arr // 通过解引用访问数组元素 printf(“第一个元素: %d\n”, (*p)[0]); // 输出10 printf(“第二个元素: %d\n”, (*p)[1]); // 输出20 #include int main() { int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int (*p)[3] = a; // p指向数组a的首地址 printf("%d\n", *(p + 1)[1]); // 输出5 return 0; } https://i-blog.csdnimg.cn/direct/b212a676ad874f6599aa0c3ef344a2fb.png https://i-blog.csdnimg.cn/direct/2dd5449d024c4507bb003b8282bf7437.png 为什莫会这样呢?大家可以思考一下
4 数组指针与指针数组的区别
  • 数组指针 :指向数组的指针,如int (*p)[10]
  • 指针数组 :存储多个指针的数组,如int *p[10]。 两者的主要区别在于:
  • 数组指针是一个整体,指向一个数组。
  • 指针数组是一个数组,存储多个指针。

二. 函数 指针

函数指针与数组指针相似 也可以用类比的方法 类比: 字符指针—— 指向字符,储存字符的地址 整形指针——指向整形,储存整形的地址 数组指针—— 指向数组,储存数组的地址 函数指针——指向函数,储存函数的地址 所以说

1 定义与基本概念

函数指针变量是指向函数的指针变量,其本质是一个指向函数地址的指针。函数指针可以像普通函数一样调用,传递参数并返回值。

返回值类型 (*指针变量名)(参数列表); 例如: int add(int a, int b) { return a + b; } int (*p)(int, int); // 定义一个指向add函数的指针

2 声明与初始化

// 普通函数 int add(int a, int b) { return a + b; } // 函数指针初始化 int (*pu)(int, int) = add;

3 调用函数

函数指针变量可以通过以下方式调用函数:

  • (*p)(参数):调用函数。
  • p(参数):等价于(*p)(参数)
  • #include int add(int a, int b) { return a + b; } int main() { int (*p)(int, int) = add; // p指向add函数 printf("%d\n", p(3, 4)); // 输出7 return 0; } https://i-blog.csdnimg.cn/direct/849b3029b45a468889ccd3872f89c694.png
4 核心特性
  • 类型严格匹配 :参数类型和返回值必须完全一致

// 错误示例 float wrongFunc(int x) { return x*1.0; ​​​​​​​ } int (*pWrong)(int) = wrongFunc; // 类型不匹配!

5 函数指针的应用

函数指针常用于以下场景:

  • 回调函数 :在某些函数调用时,允许传入一个函数作为参数。
  • 动态选择函数 :根据条件选择不同的函数执行。
  • 函数数组 :存储多个函数地址,通过索引调用。 回调函数 : void process(int x, int y, int (*callback)(int, int)) { printf(“结果:%d\n”, callback(x, y)); } int main() { process(5, 3, add); // 输出8 return 0; }   典型代码: include void print(int x) { printf(“x = %d\n”, x); } void print2(int x) { printf(“x = %d\n”, x * 2); } void (prints[])(int) = {print, print2}; // 函数指针数组 int main() { for (int i = 0; i < 2; i++) { prints ; // 调用print或print2函数 } return 0; } void test(int(arr)[5], int r, int c) { int i = 0; int j = 0; for (i = 0; i < r; i++) //行 { for (j = 0; j < c; j++) //列 { printf("%d “, arr[i][j]);//((a+i)+j) } // a[i] printf("\n”); } } int main() { int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} }; //传递的依然是数组名 - 数组名是数组首元素的地址 //实参这里传递的既然是地址,形参应该也是可以写成指针的 // test(arr, 3, 5); printf("%d\n", arr[1][2]); printf("%d\n", &arr[1][2]); printf("%p\n", test); printf("%p\n", &test); return 0; } https://i-blog.csdnimg.cn/direct/0631a9e41ca443f99d3ea8fd2e44c362.png

三. 对比总结:数组指针 vs 函数指针

特性数组指针函数指针
本质指向数组的地址指向函数的入口地址
声明语法int (*p)[N];int (*p)(int, int);
解引用操作使用(*p)[int]访问元素直接调用p(arg1, arg2)
步长计算由数组大小决定无步长概念(函数不可遍历)
典型应用多维数组操作回调函数、策略模式

四 . 常见问题解答

为什么数组指针要指定数组长度?

数组长度决定了指针运算时的步长。int (*p)[3]int (*p)[5]虽然都是数组指针,但+1操作会移动不同大小的内存。

函数指针可以指向不同参数数量的函数吗?

不可以。函数指针的类型必须与目标函数完 全一致,包括返回值类型和所有参数类型。