前言指针是C 语言的灵魂也是 C 语言最难、最重要的知识点。掌握指针才算真正入门 C 语言。指针本质围绕地址、变量类型、指针运算、解引用、传参展开同时日常开发中字符串函数底层全部依靠指针实现。本文从指针基础概念、地址类型、指针运算、数组传参、手写字符串函数、常量指针与指针常量完整区分一步步详细讲解附带原理、公式、代码案例、易错点总结适合新手系统学习、期末复习、面试备考。一、指针基础概念a. 指针的本质指针本身是一种独立的变量类型这种变量唯一的用途就是专门用来存储内存地址。普通变量存储数据值指针变量存储内存地址b. 地址的类型核心重点很多新手只知道可以取地址却不知道地址本身也是有类型的地址类型完全由被取地址的变量类型决定。举例int a;对变量a取地址a它的地址类型就是int *结论任意变量取地址后的类型 变量类型 *表格原变量定义变量类型取地址 变量地址类型int a;intaint *char ch;charchchar *double d;doubleddouble *c. 指针的运算能力必考核心公式指针不是普通数字指针进行1/-1运算时不是单纯数字 1而是向后偏移对应数据类型的字节大小。指针偏移步长公式指针地址运算能力 sizeof (去掉一个*之后的类型)详细举例int *p;去掉一个*→int运算能力sizeof(int) 4也就是p1地址向后偏移4 个字节int **p;二级指针去掉一个*→int *运算能力sizeof(int *) 864 位系统指针统一 8 字节也就是p1地址向后偏移8 个字节char *p;去掉一个*→char运算能力sizeof(char) 1也就是p1地址向后偏移1 个字节底层原理指针 1本质是跳转到下一个同类型元素的地址所以偏移量由指向的数据类型决定。d. 指针变量的定义与赋值语法int a 10; // 定义指针变量p类型 int * 存储变量a的地址 int *p a;变量名p我们称p为指针变量变量类型int *存储内容普通变量a的内存地址C 语言中只有指针变量可以存储地址普通变量无法存储地址。e. 数组作为函数参数传递指针经典应用数组在内存中所有元素地址连续存储。因此在函数传参时数组不会整体拷贝只传递数组首元素地址。只要拿到三个信息数组首地址元素的数据类型数组元素个数就可以遍历、访问整个数组的所有元素。所以函数形参中void fun(int arr[])等价于void fun(int *arr)arr本质就是指针接收数组首地址。二、指针实战手写实现字符串库函数结合指针语法手动实现库函数string.h里面全部常用函数彻底理解指针操作字符串的原理。练习 1手写mystrlen求字符串长度功能统计字符串有效长度遇到\0结束// char *p 接收字符串首地址 int mystrlen(char *p) { int len 0; // 只要不是结束符\0就计数 while (*p ! \0) { len; p; // 指针后移一位 } return len; }练习 2手写mystrncpy字符串指定长度拷贝功能从源字符串src拷贝内容到目标空间dest最多拷贝size个字节返回目标字符串首地址。char *mystrncpy(char *dest, char *src, int size) { // 保存目标起始地址用于最后返回 char *start dest; int i 0; // 拷贝同时限制最大长度size并且不能提前遇到\0结束 while (*src ! \0 i size) { *dest *src; dest; src; i; } // 手动补充字符串结束符 *dest \0; return start; }练习 3手写mystrcat字符串指定长度拼接功能将源字符串src拼接到目标字符串dest末尾限制目标空间最大容量size字节返回目标首地址。char *mystrcat(char *dest, char *src, int size) { char *start dest; // 第一步先找到dest字符串末尾\0的位置 while (*dest ! \0) { dest; } // 第二步从末尾开始拼接src内容限制总容量不越界 while (*src ! \0 (dest - start) size - 1) { *dest *src; dest; src; } // 补充结束符 *dest \0; return start; }练习 4手写mystrcmp字符串比较函数功能逐字符比较 ASCII 码值大小返回值规则s1 s2返回大于 0 的整数s1 s2返回小于 0 的负数s1 s2返回0int mystrcmp(char *s1, char *s2) { // 逐字符比较直到出现不同字符 或 到达结束符 while (*s1 ! \0 *s2 ! \0 *s1 *s2) { s1; s2; } // 两者差值即为比较结果 return *s1 - *s2; }三、常量指针 指针常量面试高频必考结合const关键字修饰指针分为常量指针、指针常量二者极易混淆本文完整区分定义、写法、含义、区别。a. 常量指针本质它是指针指向的内容是常量只读两种完全等价的写法const char *p; char const *q;p、q本身依旧是指针变量指针本身地址可以随意修改、指向可以改变指针指向的内容*p、*q只读不允许修改口诀const 修饰内容不可改指针可改*示例char a a; char b b; const char *p a; p b; // 合法指针本身可以修改指向 *p c; // 报错指向的内容只读不能修改b. 指针常量本质它是常量指针本身是常量不可修改写法char *const m;m是指针常量指针本身地址不可修改指向不可更改指针指向的内容*m可以正常修改口诀const 修饰指针变量本身指针不可改内容可改示例char a a; char b b; char *const m a; m b; // 报错指针本身是常量不能修改指向 *m c; // 合法指向的内容可以修改c. 终极区分总结口诀const在*左边修饰指向内容 → 常量指针内容只读指针可变const int *p; int const *p;const在*右边修饰指针本身 → 指针常量指针只读内容可变int *const p;拓展双向只读const int *const p;指针不可改指向内容也不可改。四、本章重点全部总结指针是专门存储内存地址的变量类型地址自带类型由原变量类型决定。指针运算核心公式*指针偏移字节数 sizeof (去掉一个)**int *1 偏移 4 字节char *1 偏移 1 字节二级指针int **1 偏移 8 字节数组函数传参只传递首地址形参本质是指针。字符串全部库函数底层均依靠指针移动、解引用实现。常量指针与指针常量区分常量指针const char *p指向内容只读指针可换指向指针常量char *const p指针本身不可改指向内容可修改区分核心看const到底修饰的是*内容还是指针变量本身。