深入理解C语言指针(三) 1. 字符指针 1 2 3 char ch = 'A' ;char *p = &ch;*p = 'B' ;
字符指针也常指向字符串字面量:
1 2 const char *message = "hello" ;printf ("%s\n" , message);
字符串字面量不应被修改,因此推荐使用 const char *。下面两种形式含义不同:
1 2 char str[] = "hello" ; const char *pstr = "hello" ;
比较字符串内容应使用 strcmp,不能使用 == 比较指针地址。
2. 数组指针 数组指针是指向数组的指针:
1 2 3 int arr[5 ] = {1 , 2 , 3 , 4 , 5 };int (*p)[5 ] = &arr;printf ("%d\n" , (*p)[2 ]);
int (*p)[5] 的阅读顺序:p 是指针,指向一个由5个 int 组成的数组。
3. 二维数组传参 二维数组传入函数后,外层数组名转换为指向第一行的指针:
1 2 3 4 5 6 7 8 9 void print_matrix (int (*matrix)[4 ], int rows) { for (int i = 0 ; i < rows; ++i) { for (int j = 0 ; j < 4 ; ++j) printf ("%d " , matrix[i][j]); printf ("\n" ); } }
也可以写成:
1 void print_matrix (int matrix[][4 ], int rows) ;
列数不能随意省略,因为编译器需要用它计算 matrix + 1 应跨过多少字节。
4. 函数指针 函数在内存中也有地址,函数指针用于保存该地址:
1 2 3 4 5 6 7 int add (int x, int y) { return x + y; } int (*operation)(int , int ) = add;int result = operation(3 , 5 );
函数指针常用于回调、排序规则、事件处理和状态机。
4.1 回调示例 1 2 3 4 int calculate (int x, int y, int (*op)(int , int )) { return op(x, y); }
调用者把行为作为参数传入,实现数据处理逻辑与具体运算解耦。
5. 函数指针数组 1 2 3 4 5 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 (*operations[3 ])(int , int ) = {add, sub, mul};
operations 是数组,每个元素都是类型为 int (*)(int, int) 的函数指针。
6. 转移表实现计算器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdio.h> 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 divide (int x, int y) { return x / y; }int main (void ) { int (*table[])(int , int ) = {NULL , add, sub, mul, divide}; int choice = 0 , x = 0 , y = 0 ; printf ("1.加 2.减 3.乘 4.除\n请选择:" ); if (scanf ("%d" , &choice) != 1 || choice < 1 || choice > 4 ) return 1 ; printf ("请输入两个整数:" ); if (scanf ("%d%d" , &x, &y) != 2 ) return 1 ; if (choice == 4 && y == 0 ) { printf ("除数不能为0。\n" ); return 1 ; } printf ("结果:%d\n" , table[choice](x, y)); return 0 ; }
转移表用数组下标直接选择函数,减少大量重复的 switch 分支。它适合命令分发、协议处理、状态机和菜单系统。
7. 复杂声明的阅读方法 1 2 3 4 int (*p)[5 ]; int *p2[5 ]; int (*func)(int , int ); int (*table[4 ])(int , int );
从变量名开始,先处理括号和下标,再向外阅读。复杂类型可以使用 typedef 简化:
1 2 typedef int (*BinaryOperation) (int , int ) ;BinaryOperation table[4 ];
8. 总结 高级指针的价值不在复杂语法,而在于表达“数据布局”和“可替换行为”。数组指针解决多维数据寻址,函数指针与转移表则为回调和模块化分发提供基础。
Lichermione
天行健,君子以自强不息;
地势坤,君子以厚德载物。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LichermioneX 的博客 !