指针核心知识:5篇系统梳理4

发布时间:2026/7/14 10:37:57

指针核心知识:5篇系统梳理4 本系列将通过 5 篇文章系统梳理指针核心知识欢迎关注专栏指针梳理获取完整内容1.字符指针变量字符指针变量的类型是char*代码举例//字符指针使用举例 #include stdio.h int main() { char a w; char* ch a; *ch z; printf(%c\n, a); return 0; }易错点——思考以下代码是将hello world放到指针变量pstr里了吗#include stdio.h int main() { char* pstr hello world; printf(%s\n, pstr); return 0; }初学者容易误解这段代码以为 pstr 存储了整个字符串内容但实际上它只保存了字符串首字符的地址。2.《剑指offer》的一道字符串笔试题#include stdio.h int main() { char str1[] hello bit.; char str2[] hello bit.; const char* str3 hello bit.; const char* str4 hello bit.; if (str1 str2) printf(str1 and str2 are same\n); else printf(str1 and str2 are not same\n); if (str3 str4) printf(str3 and str4 are same\n); else printf(str3 and str4 are not same\n); return 0; }拆解str1和str2char str1[ ]hello bit.会在栈内存中开辟一块独立空间把字符串内容拷贝进去char str2[ ]hello bit.会再开辟另一块独立空间把字符串内容拷贝进去即使内容完全一样它们是两个不同的数组所以str1和str2指向的地址不同用比较时比较的是指针地址因此结果为falsestr3和str4hello bit.是字符串常量C/C会把它放在只读数据段常量区编译器会做常量折叠优化相同内容的字符串常量只会存一份节省空间const char* str3和const char* str4都指向这个唯一的常量字符串所以地址相同用比较时地址相等因此结果为true3.数组指针变量定义数组指针变量存放的是数组的地址能够指向数组的指针变量提问下面哪个是数组指针变量int* p1[10]; int(*p2)[10];答案是第二个[ ]的优先级要高于*号所以必须加上()来保证p先和*结合int(*p2)[10];解释p2先和*结合说明p是一个指针变量然后指针指向的是一个大小为10个整型的数组。所以p是一个指针指向一个数组叫数组指针。数组指针变量的初始化int arr[10] { 0 }; int(*p)[10] arr;数组指针类型解析int (*p) [10] arr; | | | | | | | | p指向数组的元素个数 | p是数组指针变量名 p指向的数组的元素类型4.二维数组传参的本质二维数组本质上是由多个一维数组组成的数组结构。具体来说二维数组的每个元素本身就是一个一维数组。因此二维数组的首元素实际上就是它的第一行数据这个首元素本身就是一个完整的一维数组。因此依据数组名代表数组首元素地址这一规则二维数组名实际上表示第一行的地址即一维数组的地址。以前文示例为例第一行的一维数组类型为int[5]因此第一行地址的类型应为数组指针类型int(*)[5]。这意味着二维数组传参本质上是地址传递传递的是第一行这个一维数组的地址。5.函数指针变量函数指针变量是用来存放函数地址的未来通过地址能够调用函数提问函数是否有地址呢#include stdio.h void test() { printf(hehe\n); } int main() { printf(test: %p\n, test); printf(test: %p\n, test); return 0; }函数是有地址的函数名就是函数的地址当然也可以通过函数名的方式获得函数的地址。这里两种取函数地址的方式没有区别不像数组函数指针类型解析int (*pf3) (int x, int y) | | ------------ | | | | | pf3指向函数的参数类型和个数的交代 | 函数指针变量名 pf3指向函数的返回类型 int (*) (int x, int y) //pf3函数指针变量的类型举例使用#include stdio.h int Add(int x, int y) { return x y; } int main() { int(*pf3)(int, int) Add; printf(%d\n, (*pf3)(2, 3)); printf(%d\n, pf3(3, 5)); return 0; }6.typedef关键字typedef是用来类型重命名的可以将复杂的类型简单化比如你觉得 unsigned int 写起来不方便如果能写成 uint 就方便多了那么我们可以使用typedef unsigned int uint; //将unsigned int 重命名为uint如果是指针类型能否重命名呢其实也是可以的比如将 int* 重命名为 ptr_t ,这样写typedef int* ptr_t;但是对于数组指针和函数指针稍微有点区别比如我们有数组指针类型 int(*)[5] ,需要重命名为 parr_t 那可以这样写typedef void(*pfun_t)(int);//新的类型名必须在*的右边7.函数指针数组要把函数的地址存到一个数组中那这个数组就叫函数指针数组int (*parr1[3])(int,int);parr1 先和 [ ] 结合说明parr1是数组,数组里的元素是int (*)(intint) 类型的函数指针8.函数指针数组的应用——转移表简易计算器的一般实现#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; } void menu() { printf(---------------------------------\n); printf(------- 1.加法 2.减法 ----------\n); printf(------- 3.乘法 4.除法 ----------\n); printf(---------- 0.退出 --------------\n); printf(---------------------------------\n); } int main() { int x, y; int input 1; int ret 0; do { menu(); printf(请选择); scanf(%d, input); switch (input) { case 1: printf(输入操作数); scanf(%d %d, x, y); ret add(x, y); printf(ret %d\n, ret); break; case 2: printf(输入操作数); scanf(%d %d, x, y); ret sub(x, y); printf(ret %d\n, ret); break; case 3: printf(输入操作数); scanf(%d %d, x, y); ret mul(x, y); printf(ret %d\n, ret); break; case 4: printf(输入操作数); scanf(%d %d, x, y); ret div(x, y); printf(ret %d\n, ret); break; case 0: printf(退出程序\n); break; default: printf(选择错误\n); break; } } while (input); return 0; }使用函数指针数组实现#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; } void menu() { printf(---------------------------------\n); printf(------- 1.加法 2.减法 ----------\n); printf(------- 3.乘法 4.除法 ----------\n); printf(---------- 0.退出 --------------\n); printf(---------------------------------\n); } int main() { int x, y; int input 1; int ret 0; int(*p[5])(int x, int y) { 0, add, sub, mul, div }; //转移表 do { menu(); printf(请选择); scanf(%d, input); if ((input 4 input 1)) { printf(输入操作数); scanf(%d %d, x, y); ret (*p[input])(x, y); printf(ret %d\n, ret); } else if (input 0) { printf(退出计算器\n); } else { printf(输入有误\n); } } while (input); return 0; }switch—case版本痛点代码高度重复每个case里都要写「输入操作数→调用函数→打印结果」的模板代码。扩展性差如果要新增「取模、幂运算」就要多写一个case代码越来越长而函数指针数组的版本更好// 声明一个数组每个元素是「指向返回 int、参数为两个 int 的函数」的指针 int (*p[5])(int x, int y) {0, add, sub, mul, div};用数组下标直接调用函数// input 是用户选择的 1~4直接作为数组下标 ret (*p[input])(x, y); // 也可以写成 ret p[input](x, y);优势代码极简去掉了所有case分支用一行调用替代。扩展性强新增运算只需在数组里加一个函数指针不用改主逻辑。完由于单篇文章无法涵盖所有知识其他内容请移步至本专栏其他文章指针梳理

相关新闻