news 2026/5/7 23:58:13

内存指针是什么?为什么指针还要有偏移量?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
内存指针是什么?为什么指针还要有偏移量?

原文链接: 内存指针是什么?为什么指针还要有偏移量? < Ping通途说

1. 什么是内存指针、偏移量?

内存指针是一个存储内存地址的变量,它指向计算机内存中的某个特定位置。可以把它想象成:

  • 现实世界的比喻:指针就像房子的门牌号,告诉你某个数据“住在”内存的哪个位置
  • 本质:指针本身也是一个变量,但它的值不是普通数据,而是内存地址
int num = 42; // 普通变量,存储数字42 int *ptr = &num // 指针变量,存储num的内存地址

而偏移量是让指针真正强大的关键特性,主要可以用于数组访问、结构体和类成员访问、数据遍历,甚至动态操作内存。

以数组访问为例,可以很明显看出其功能,这不就是主流编程语言都有的索引。

int arr[5] = {10, 20, 30, 40, 50}; int *ptr = arr; // 指向数组首元素 // 通过偏移访问 int third = *(ptr + 2); // 访问第三个元素(30)

以及令人望而生畏的手动内存管理,实际上在指针上增加偏移值以指向对应内存进行处理:

int *buffer = malloc(100 * sizeof(int)); // 填充第50个位置 *(buffer + 49) = 123;

但偏移量不跟数组的索引一样,而是根据数据类型自动缩放其范围。MySQL中常见的int和tinyint,大家应该都知道一个占4字节,另一个就是占1字节。由于C没有tinyint,所以用char代替

int *ptr = 0x1000; // 假设内存地址 ptr + 1; // 实际上指向 0x1004(int通常是4字节) ptr + 3; // 实际上指向 0x100C(跳过4x3=12字节) char *cptr = 0x1000; cptr + 1; // 指向 0x1001(char是1字节)

因此需要注意:偏移的不是"第几个值",而是"第几个同类型元素"

2. 再说简单些!以及怎么取一整段数据?

你应该知道,数据最终呈现的格式就是1和0,因此在内存中也都是0/1的位。

指针本身就是一段数据的起点,偏移值就是取起点的第n个同类型元素。

指针偏移就像在内存中"跳格子",每个格子的大小由指针类型决定,你可以精确控制要访问哪个或哪几个连续格子中的数据。

另外需要注意,偏移量的范围不得超出内存范围,否则轻则软件崩溃,重则系统崩溃(蓝屏)。

由于偏移值只能指向一个位置,C也没有Python那样直接通过data[0,5]取范围值,因此主要通过for遍历来操作一段数据:

1. 数组表示法(最简单)

int arr[10] = {0,1,2,3,4,5,6,7,8,9}; int *start = &arr[2]; // 从第3个元素开始 int *end = &arr[7]; // 到第8个元素结束 // 取第3到第8个元素 for(int *p = start; p <= end; p++) { printf("%d ", *p); // 输出: 2 3 4 5 6 7 }

2. 结构体/对象的连续块

struct Point { //定义一个点的结构体 int x; int y; }; struct Point points[5] = {{1,2}, {3,4}, {5,6}, {7,8}, {9,10}}; struct Point *ptr = points; // 取连续3个Point for(int i = 0; i < 3; i++) { printf("Point %d: (%d, %d)\n", i, (ptr + i)->x, // 或 ptr[i].x (ptr + i)->y); }

3. 动态内存操作

// 分配连续内存块 int *buffer = malloc(50 * sizeof(int)); // 方法1: 指针移动 int *current = buffer; for(int i = 0; i < 50; i++) { *current = i * 2; // 赋值 current++; // 指针向后移动一个int } // 方法2: 数组下标 for(int i = 0; i < 50; i++) { buffer[i] = i * 2; }

再用一个内存布局示例来展示一下:

假设内存中有这样的int数组:

地址C写法
0x100010arr[0]
0x100420arr[1]
0x100830arr[2]
0x100C40arr[3]
0x101050arr[4]
int *ptr = 0x1008; // 指向30 // 取连续3个值 int val1 = *(ptr + 0); // 30 int val2 = *(ptr + 1); // 40 int val3 = *(ptr + 2); // 50

实际应用:图像处理示例

// 假设处理1280x720的图像,每个像素4字节(RGBA) int width = 1280; int height = 720; uint8_t *image = malloc(width * height * 4); // 取第100行开始的连续10行 int start_row = 100; int row_count = 10; uint8_t *region_start = image + (start_row * width * 4); uint8_t *region_end = region_start + (row_count * width * 4); // 处理这个区域 for(uint8_t *p = region_start; p < region_end; p += 4) { // 每个像素4字节: p[0]=R, p[1]=G, p[2]=B, p[3]=A p[0] = 255; // 设置红色 }

3. 越界访问的"界"是什么?

界有两种,一种是系统分配给软件的内存范围,另一种就是数据结构范围。

1.操作系统层面:进程内存边界

每个程序运行时,操作系统为其分配一个虚拟地址空间(例如:0x00000000到0xFFFFFFFF)

// 试图访问非法地址 int *ptr = (int*)0xFFFFFFFF; // 可能超出进程空间 *ptr = 42; // 触发段错误(Segmentation Fault) // 后果:程序立即崩溃(操作系统保护) // 保护机制:MMU(内存管理单元)+ 页表

2.程序层面:数据结构边界

int arr[10]; arr[15] = 42; // 越过了数组边界但仍在进程空间内

导致的后果:软件可能不会立即崩溃,但会破坏其他变量数据(堆栈破坏),导致程序逻辑错误以及安全漏洞(缓冲区溢出攻击)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 19:09:48

安卓驱动开发工程师:深入技术核心,驱动智能未来

深圳达实智能股份有限公司 安卓驱动开发工程师 职位信息 负责安卓系统底层驱动的设计、开发、调试、集成与性能优化工作。 负责Android Framework及内核等系统框架层的调优,关键模块开发实现及调试定位。 系统API设计和开发,安卓SDK定制和维护。 二、 任职要求: 1. 基础要求…

作者头像 李华
网站建设 2026/5/6 18:19:51

协鑫集成高级AI开发工程师职位深度解析:职责、能力与面试指南

协鑫集成 高级AI开发工程师 职位信息 职位详情: 1.探索、跟踪国内外领先的AI技术、产品方案,推动其在公司内应用,提升企业运营效率,生产效率。 2.协调各部门团队,包括研发、工艺、生产、职能等,确保AI项目目标实现。 3.结合AI背景和行业需求,为企业数字化、智能化提供指…

作者头像 李华
网站建设 2026/5/7 21:10:28

Snapd和Apt—Linux 上两种完全不同的软件包管理系统

Snapd 和 Apt 是 Linux 上两种完全不同的软件包管理系统&#xff0c;各有优劣。以下是详细对比&#xff1a; 核心区别一览 特性Apt (传统)Snapd (现代)设计年代1998年 (Debian)2014年 (Ubuntu)软件包格式.deb.snap依赖处理共享系统库&#xff0c;自动解决依赖自带所有依赖&…

作者头像 李华
网站建设 2026/5/7 1:44:50

ESP32 的宝藏开源项目:ESP32 - Bus - Pirate 打造硬件调试瑞士军刀

大家好&#xff0c;我是杂烩君。当你手里拿着一个ESP32开发板&#xff0c;除了做物联网项目&#xff0c;还能干什么&#xff1f; 可以借助ESP32-Bus-Pirate把ESP32板子变成了一把"瑞士军刀"&#xff0c;能够与20多种数字协议和无线协议进行交互。 1. ESP32-Bus-Pir…

作者头像 李华
网站建设 2026/5/1 14:28:25

【ICLR26-加州大学】GEN2SEG:生成模型实现可泛化的实例分割

文章&#xff1a;GEN2SEG: GENERATIVE MODELS ENABLE GENERALIZABLE INSTANCE SEGMENTATION代码&#xff1a;https://reachomk.github.io/gen2seg单位&#xff1a;加州大学戴维斯分校一、问题背景人类仅凭有限经验就能识别各类陌生物体&#xff0c;而传统视觉模型的“零样本迁移…

作者头像 李华
网站建设 2026/5/1 13:33:18

股市估值差异对国际技术标准制定的影响

股市估值差异对国际技术标准制定的影响关键词&#xff1a;股市估值差异、国际技术标准制定、技术创新、市场竞争、产业发展摘要&#xff1a;本文深入探讨了股市估值差异对国际技术标准制定的影响。首先介绍了研究的背景、目的、范围以及预期读者等内容。接着阐述了股市估值差异…

作者头像 李华