C语言数组指针变量函数指针变量
(C语言)《数组指针变量》《函数指针变量》
一. 数组 指针
指针数组:存放指针的数组 那数组指针是什么?
1 定义与基本概念
数组指针变量是指向数组的指针变量,其本质是一个指向数组首地址的指针。数组名本身即为数组首地址,因此数组指针变量可以直接通过数组名或指针运算符访问数组元素。 想要更加容易理解数组指针,可以类比字符/数组指针 类比: 字符指针—— 指向字符,储存字符的地址 整形指针——指向整形,储存整形的地址 数组指针—— 指向数组,储存数组的地址 例如:int arr[10]={0} 那么数组arr的地址就是 &arr
&加数组名 就是 数组的地址
2 声明与初始化
int arr[3] = {10, 20, 30}; // 普通数组
int (*p)[3] = &arr // 数组指针初始化
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; }为什莫会这样呢?大家可以思考一下
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;
}
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;
}
三. 对比总结:数组指针 vs 函数指针
特性 | 数组指针 | 函数指针 |
---|---|---|
本质 | 指向数组的地址 | 指向函数的入口地址 |
声明语法 | int (*p)[N]; | int (*p)(int, int); |
解引用操作 | 使用(*p)[int] 访问元素 | 直接调用p(arg1, arg2) |
步长计算 | 由数组大小决定 | 无步长概念(函数不可遍历) |
典型应用 | 多维数组操作 | 回调函数、策略模式 |
四 . 常见问题解答
为什么数组指针要指定数组长度?
数组长度决定了指针运算时的步长。int (*p)[3]
与int (*p)[5]
虽然都是数组指针,但+1操作会移动不同大小的内存。
函数指针可以指向不同参数数量的函数吗?
不可以。函数指针的类型必须与目标函数完 全一致,包括返回值类型和所有参数类型。