news 2026/4/18 23:46:31

Day 08:C 语言指针超详细详解:指针基础、运算、字符串函数实现、const 指针

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 08:C 语言指针超详细详解:指针基础、运算、字符串函数实现、const 指针

前言

指针是C 语言的灵魂,也是 C 语言最难、最重要的知识点。掌握指针,才算真正入门 C 语言。指针本质围绕地址、变量类型、指针运算、解引用、传参展开,同时日常开发中字符串函数底层全部依靠指针实现。本文从指针基础概念、地址类型、指针运算、数组传参、手写字符串函数、常量指针与指针常量完整区分,一步步详细讲解,附带原理、公式、代码案例、易错点总结,适合新手系统学习、期末复习、面试备考。


一、指针基础概念

a. 指针的本质

指针本身是一种独立的变量类型,这种变量唯一的用途就是:专门用来存储内存地址

普通变量:存储数据值指针变量:存储内存地址

b. 地址的类型(核心重点)

很多新手只知道&可以取地址,却不知道地址本身也是有类型的,地址类型完全由被取地址的变量类型决定。

  1. 举例
int a;

对变量a取地址&a,它的地址类型就是int *

结论

任意变量取地址后的类型 = 变量类型 +*

表格

原变量定义变量类型取地址 & 变量地址类型
int a;int&aint *
char ch;char&chchar *
double d;double&ddouble *

c. 指针的运算能力(必考核心公式)

指针不是普通数字,指针进行+1/-1运算时,不是单纯数字 + 1,而是向后偏移对应数据类型的字节大小。指针偏移步长公式:

指针地址运算能力 = sizeof (去掉一个*之后的类型)

详细举例:

  1. int *p;去掉一个*int运算能力:sizeof(int) = 4也就是p+1,地址向后偏移4 个字节

  2. int **p;(二级指针)去掉一个*int *运算能力:sizeof(int *) = 8(64 位系统指针统一 8 字节)也就是p+1,地址向后偏移8 个字节

  3. char *p;去掉一个*char运算能力:sizeof(char) = 1也就是p+1,地址向后偏移1 个字节

底层原理:指针 + 1,本质是跳转到下一个同类型元素的地址,所以偏移量由指向的数据类型决定。

d. 指针变量的定义与赋值

  1. 语法
int a = 10; // 定义指针变量p,类型 int * ,存储变量a的地址 int *p = &a;
  • 变量名:p,我们称p指针变量
  • 变量类型:int *
  • 存储内容:普通变量a的内存地址
  • C 语言中只有指针变量可以存储地址,普通变量无法存储地址。

e. 数组作为函数参数传递(指针经典应用)

数组在内存中所有元素地址连续存储。因此在函数传参时,数组不会整体拷贝,只传递数组首元素地址

只要拿到三个信息:

  1. 数组首地址
  2. 元素的数据类型
  3. 数组元素个数

就可以遍历、访问整个数组的所有元素。

所以函数形参中:

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 码值大小返回值规则:

  1. s1 > s2,返回大于 0 的整数
  2. s1 < s2,返回小于 0 的负数
  3. s1 == s2,返回0
int 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;
  1. pq本身依旧是指针变量,指针本身地址可以随意修改、指向可以改变
  2. 指针指向的内容*p*q只读,不允许修改
  3. 口诀:const 修饰,内容不可改,指针可改*

示例:

char a = 'a'; char b = 'b'; const char *p = &a; p = &b; // 合法:指针本身可以修改指向 *p = 'c'; // 报错:指向的内容只读,不能修改

b. 指针常量

本质:它是常量,指针本身是常量不可修改写法:

char *const m;
  1. m是指针常量,指针本身地址不可修改,指向不可更改
  2. 指针指向的内容*m可以正常修改
  3. 口诀:const 修饰指针变量本身,指针不可改,内容可改

示例:

char a = 'a'; char b = 'b'; char *const m = &a; m = &b; // 报错:指针本身是常量,不能修改指向 *m = 'c'; // 合法:指向的内容可以修改

c. 终极区分总结口诀

  1. const*左边:修饰指向内容 → 常量指针,内容只读,指针可变
    const int *p; int const *p;
  2. const*右边:修饰指针本身 → 指针常量,指针只读,内容可变
    int *const p;
  3. 拓展(双向只读):
    const int *const p;
    指针不可改,指向内容也不可改。

四、本章重点全部总结

  1. 指针是专门存储内存地址的变量类型,地址自带类型,由原变量类型决定。
  2. 指针运算核心公式:*指针偏移字节数 = sizeof (去掉一个)**
    • int *+1 偏移 4 字节
    • char *+1 偏移 1 字节
    • 二级指针int **+1 偏移 8 字节
  3. 数组函数传参,只传递首地址,形参本质是指针。
  4. 字符串全部库函数底层均依靠指针移动、解引用实现。
  5. 常量指针与指针常量区分:
    • 常量指针const char *p,指向内容只读,指针可换指向
    • 指针常量char *const p,指针本身不可改,指向内容可修改
  6. 区分核心:看const到底修饰的是*(内容),还是指针变量本身。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 23:42:18

终极指南:如何用Public APIs快速找到你需要的免费API服务

终极指南&#xff1a;如何用Public APIs快速找到你需要的免费API服务 【免费下载链接】public-apis A collaborative list of public APIs for developers 项目地址: https://gitcode.com/GitHub_Trending/publ/public-apis 还在为寻找合适的API而烦恼吗&#xff1f;想象…

作者头像 李华
网站建设 2026/4/18 23:42:18

【技术解析】MaskNet:用Instance-Guided Mask与MaskBlock革新深度推荐模型

1. 深度推荐模型的瓶颈与突破 推荐系统发展到今天&#xff0c;DNN模型已经成为标配。但我在实际业务中发现一个有趣现象&#xff1a;很多团队把DNN层数越堆越高&#xff0c;效果提升却越来越有限。这背后其实隐藏着一个关键问题——传统DNN在特征交叉建模上存在先天不足。 FNN、…

作者头像 李华
网站建设 2026/4/18 23:41:46

Django DRF权限怎么加_IsAuthenticated与自定义BasePermission

DRF中IsAuthenticated未生效最常见的原因是权限类未正确注册到视图或全局配置&#xff1b;必须显式声明permission_classes[IsAuthenticated]&#xff0c;且多个权限类需全部返回True才通过&#xff0c;顺序不可颠倒。DRF里IsAuthenticated为什么没生效&#xff1f;最常见的原因…

作者头像 李华
网站建设 2026/4/18 23:41:16

Apache Doris 1.0 极速进化:向量化引擎与湖仓一体实战解析

1. 向量化引擎&#xff1a;从原理到性能飞跃 第一次接触Apache Doris的向量化引擎时&#xff0c;我正被一个千万级数据表的聚合查询性能问题困扰。原本需要15秒的查询&#xff0c;在开启向量化引擎后直接降到3秒&#xff0c;这种性能提升让我决定深入研究它的技术原理。 向量…

作者头像 李华