跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

C 语言指针与数组的深度关联及实战应用

C 语言中数组名常被视为指向首元素的常量指针,下标访问等价于指针偏移运算。通过指针算术可高效遍历、求和或逆序数组,但需注意越界风险及函数传参时的长度丢失问题。指针数组用于存放多个指针变量,常用于字符串管理;数组指针则指向整个数组结构,常用于二维数组处理。掌握二者区别及内存布局是底层开发的关键。

laoliangsh发布于 2026/3/24更新于 2026/7/2836 浏览
C 语言指针与数组的深度关联及实战应用

C 语言指针与数组的深度关联及实战应用

在这里插入图片描述

在 C 语言开发中,指针和数组的纠缠关系往往是新手最容易踩坑的地方。这篇文章不讲枯燥的定义,直接聊聊数组名的本质、指针算术运算的实际用法,以及指针数组和数组指针的区别。搞懂这些,你在处理内存、遍历数据时会更从容。

数组名与指针的关系

很多初学者容易把数组名当成普通的变量,其实它在大多数情况下会被编译器隐式转换为指向首元素的常量指针。这意味着你可以用指针的方式去访问它,但它本身不能变。

数组名的本质

看这段代码:

#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    printf("数组首元素地址:%p\n", arr);
    printf("数组首元素地址:%p\n", &arr[0]);
    printf("数组首元素值:%d\n", *arr);
    return 0;
}

运行结果会显示 arr 和 &arr[0] 的地址完全一致,都是数组第一个元素的地址。通过 *arr 解引用也能拿到第一个元素的值。这验证了数组名确实能当指针用。

⚠️ 注意:数组名是常量指针,你不能修改它的值。下面这种写法是非法的:

int arr[5];
arr++; // 错误!数组名是常量,不能自增

下标访问与指针等价性

C 语言规定,arr[i] 在底层完全等价于 *(arr + i)。这是指针操作数组的核心逻辑。指针算术运算会根据元素类型自动计算偏移量,比如 int 占 4 字节,arr + 1 就会跳过 4 个字节指向下一个元素。

#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int i;
    for (i = 0; i < 5; i++) {
        printf("arr[%d] = %d, *(arr + %d) = %d\n", i, arr[i], i, *(arr + i));
    }
    return 0;
}

两种写法输出结果完全一样,但理解背后的偏移机制对调试很有帮助。

指针操作数组的实战案例

理解了原理,我们来看看怎么用指针让代码更简洁高效。

案例一:指针遍历求和

需求是用指针遍历数组并计算总和。这里有个小技巧,利用 sizeof 动态获取长度。

#include <stdio.h>

int main() {
    int arr[6] = {1, 2, 3, 4, 5, 6};
    int sum = 0;
    int *p = arr; // 指针 p 指向数组首元素
    int len = sizeof(arr) / sizeof(arr[0]); // 通用长度计算方法

    for (int i = 0; i < len; i++) {
        sum += *p;
        p++; // 指针自增,指向下一个元素
    }
    printf("数组元素总和:%d\n", sum);
    return 0;
}

运行结果是 21。注意 sizeof(arr) / sizeof(arr[0]) 这种写法适用于任意类型的静态数组,比硬编码数字更安全。

案例二:指针逆序存放

不用额外空间,直接用双指针交换实现数组逆序。

#include <stdio.h>

void reverseArray(int *arr, int len) {
    int *left = arr;           // 指向首元素
    int *right = arr + len - 1; // 指向尾元素
    int temp;

    while (left < right) {
        temp = *left;
        *left = *right;
        *right = temp;
        left++;
        right--;
    }
}

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int len = sizeof(arr) / sizeof(arr[0]);
    int *p = arr;

    printf("原数组:");
    for (int i = 0; i < len; i++) {
        printf("%d ", *(p + i));
    }
    printf("\n");

    reverseArray(arr, len);

    printf("逆序数组:");
    for (int i = 0; i < len; i++) {
        printf("%d ", *(p + i));
    }
    printf("\n");
    return 0;
}

⚠️ 坑点提醒:在函数内部使用 sizeof(arr) 得到的只是指针的大小(通常是 4 或 8 字节),而不是数组实际大小。所以传递数组给函数时,必须同时传递长度参数。

指针数组与数组指针的区别

这两个概念名字很像,但用途完全不同,面试和工作中经常考到。

指针数组

定义:存放指针的数组。 格式:类型 *数组名 [长度];

每个元素都是一个指针变量,常用于管理多个字符串。

#include <stdio.h>

int main() {
    char *strArr[3] = {"C 语言", "指针", "数组"};
    for (int i = 0; i < 3; i++) {
        printf("%s\n", strArr[i]);
    }
    return 0;
}

数组指针

定义:指向整个数组的指针。 格式:类型 (*指针名)[长度];

它指向的是一个完整的数组结构,常用于二维数组操作。

#include <stdio.h>

int main() {
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*p)[3] = arr; // 数组指针,指向包含 3 个 int 元素的数组

    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", *(*(p + i) + j));
        }
        printf("\n");
    }
    return 0;
}

⚠️ 关键细节:定义数组指针时,(*p) 的括号绝对不能省。如果写成 int *p[3],那就变成了指针数组,含义天差地别。

常见问题与解决方案

问题一:指针越界访问

❌ 错误示范:

int arr[3] = {1, 2, 3};
int *p = arr;
for (int i = 0; i < 5; i++) {
    printf("%d\n", *p++); // 越界访问,读取随机值
}

✅ 解决思路: 严格根据数组长度控制循环次数。永远不要假设指针后面还有合法数据,使用 sizeof 计算长度是最稳妥的方式。

问题二:混淆两者定义

❌ 原因:定义时漏掉括号,或者没分清是指针的集合还是指向集合的指针。 ✅ 口诀: 指针数组是 类型 *数组名 [](存指针); 数组指针是 类型 (*指针名) [](指整体)。

本章小结

  1. 数组名本质是常量指针,arr[i] 等价于 *(arr + i)。
  2. 指针算术运算能高效完成遍历、求和、逆序等操作,但要注意函数传参时的长度丢失问题。
  3. 指针数组存的是地址,数组指针存的是数组整体,定义格式差一个括号。
  4. 操作内存务必小心越界,控制好指针边界是基本功。

目录

  1. C 语言指针与数组的深度关联及实战应用
  2. 数组名与指针的关系
  3. 数组名的本质
  4. 下标访问与指针等价性
  5. 指针操作数组的实战案例
  6. 案例一:指针遍历求和
  7. 案例二:指针逆序存放
  8. 指针数组与数组指针的区别
  9. 指针数组
  10. 数组指针
  11. 常见问题与解决方案
  12. 问题一:指针越界访问
  13. 问题二:混淆两者定义
  14. 本章小结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 文心一言:百度国产大模型的技术与使用指南
  • 直流无刷电机 FOC 控制算法原理与 STM32 实战
  • 单细胞虚拟基因敲除分析及高级可视化:从预处理到 UMAP
  • 本地离线部署 AI 大模型:Ollama + Qwen3.5 + OpenClaw 实战指南
  • macOS 动态壁纸文件路径及删除方法
  • VS Code 中 GitHub 扩展登录报错:尚未完成授权此扩展使用 GitHub 的操作
  • TqSdk与VnPy两款Python量化框架对比
  • OpenClaw 联网工具配置指南:提升 AI 实时信息获取能力
  • TRAE AI 智能体实现 Vue 3 + Node.js + MySQL 全栈项目实战
  • 前端 JS 加载失败处理方案:重试与多源备份策略
  • Python 音乐下载工具 Musicdl 多平台支持使用指南
  • 前端 JS 加载失败处理方案:重试与多源备份策略
  • AR 健身教练:形随心动 - 基于 Rokid CXR-M SDK 的实践落地
  • 基于离散化与线段树的机器人摧毁墙壁最大数量解法
  • DM0 面向物理 AI 的 VLA:VLM 混入物理数据预训练与流匹配动作专家
  • 基于 OpenAI Whisper-large-v3 的本地化语音识别服务部署
  • 高企年报自动化系统实战:用低代码替代 Excel 手工填报
  • Day.js 轻量级日期处理核心用法
  • 深入理解 C++ STL 优先队列 priority_queue 原理与实现
  • 复现 StreamVLN 具身导航:流式视觉语言导航实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online