当前位置: 首页 > news >正文

嵌入式Day12--指针

1.特点

  • 让代码更加简洁

    高效指针传参通过指针直接操作数据,避免不必要的数据拷贝,提高程序运行效率。
  • 提供直接访问内存的操作

    指针存储的是内存地址,可以直接读写该地址的数据,灵活控制内存。
  • 利用指针可以直接操作硬件

    指针可以直接访问硬件寄存器或内存映射的硬件设备。

2.概念

  • 内存,存储运行时的数据。
  • 内存地址: 计算机需要对物理内存进行管理。因为内存空间大,给每个存储单元(1byte)分配一个编号。这个编号就是内存地址,并且是线性连续的。
  • 指针就是指针变量,是专门用来存储内存地址的变量。 在32bit操作系统下任意类型的指针大小为4byte(0-0xffffffff)。在64bit操作系统下,任意类型的指针大小为8byte(0-0xffffffffffffffff)
  • 指针的类型是多种多样的。例如:int*(整形的),char* (字符指针),double*(浮点类型指针)任意类型的指针大小都是一致的,用指针可以表示任意的数据。
  • 通过变量名访问内存的方式称为直接访问。 如果用指针方式访问称为间接访问。
  • 当定义变量后,变量名会和对应的内存空间进行关联。变量名是内存的一个别名。
  • 内存地址是一个编号,这个编号和int类型在c语言中是不同的两种类型,支持的运算符和操作是不同。

3.相关的运算符

3.1&(取地址)运算符

获得变量在内存空间中的地址编号(单目运算符,从右向左结合。)

只有变量(左值)在内存中有明确位置的值才能使用,常量和表达式不能进行&操作

int a =20; &a; // 获得a 变量在内存中的地址。 输入需要输出,通常使用%p来输出 取地址操作相当于升级操作 变量升级为对应类型的指针

3.2 *(解引用)运算符

获得指针指向的空间或者对应空间中的值,通过指针间接访问它指向的数据。

*运算符连接的内容必须为指针类型,不能是普通变量类型

如果直接使用*对应的表达式,表达式值为:该指针指向空间中的值

int a =20; &a; 指针类型 *&a; // 20 int 解引用操作相当于降级操作 指针降级为变量类型。 解引用操作的过程 1. 找到指针中存储的地址 2. 根据指针的基类型(int * 的基类型是int) 确定占用内存大小 3. 取出:从地址开始的地方+基类型的大小取出数据。 取地址操作和解引用操作互为反操作。

4.定义

不能使用未经初始化的指针

int *p; //指向空间的范围为4字节 char *p; //指向空间的范围为1字节 float *p; //指向空间的范围为4字节 double *p; //指向空间的范围为8字节 int *p, *q;

5.初始化

指针变量定义好后一定要初始化。如果不初始化会存储随机地址。

5.1野指针

未经初始化的指针、指向已经被释放空间的指针、超出作用范围的指针,称为野指针

5.2空指针

不明确指向任何有效对象或内存地址的指针、指向内存地址为0x0的指针,称为空指针

用NULL来表示,它的值为 0

内存地址0x0空间为只读空间,不能赋值,NULL指针不能执行*p = value操作

int *p_i; // 定义了一个整形指针 int* .只能存储整形变量的地址 char* p_c = 0 ; // 都是8 个字节。 空指针 double* p_d ; // 野指针 short* p_s = NULL; //空指针 ,逻辑上先指向0地址稍后再给一个合理的地址

6.指针的访问

变量的访问分为直接和间接访问

// 初始化 int i_a =20; p_i = &i_a; // 正常初始化 // &20; 只能是变量执行取址操作 // &(i_a +10); printf("a is addr %p\n",&i_a); printf("p_i is %p\n",p_i); printf("a is %d\n",i_a); // 直接访问 printf("指针访问,a is %d\n",*p_i); // 间接访问 i_a = 30;// 直接访问 printf("i_a = 30 ,a is %d\n",i_a); *p_i = 50;// 间接访问 printf("*p_i =50, a is %d\n",*p_i);

内存存储如下:

7.指针的算术运算

算术运算(整形):+ - * / % ++ --
指针的算术运算:+ - ,++ -- (一般对数组进行访问的时候,会使用算术运算符)。

指针的加法 int a =20; // 0x2000 int int *p = &a; // 0x2000 &a-> int * printf("a is addr %p\n",&a); printf("p is addr %p\n",p); p=p+1; // p 中存储的地址值 变大。 p中原来的地址 + sizeof(基类型 ,4byte) 0xebbc 0xebc0 printf("p+1 is addr %p\n",p);

#include <stdio.h> int main() { int a =20; // 0x2000 int int *p = &a; // 0x2000 &a-> int * printf("a is addr %p\n",&a); printf("p is addr %p\n",p); #if 0 // 减法 p=p-1; printf("p-1 is addr %p\n",p); 先获得p 指针中存储的地址,和sizeof(基类型)的大小进行相减操作。 // p = p*2; // 乘法没有意义 // p = p/2; // 没有意义 // p = p%4; //没有意义 // 加法 先获得p指针中存储的地址,和sizeof(基类型)的大小进行相加操作。 p++; // p = p+1; printf("p+1 is addr %p\n",p); #endif // 先获得p指针中存储的地址,和sizeof(基类型)的大小进行相减操作。 p--; printf("p-1 is addr %p\n",p); nt b = 20; int *pb = &b; //p+pb ; 两个指向不同变量的指针,进行相加没有意义。 // p - pb; 两个指向不同变量的指针,进行相减没有意义。 //如果这两个指针,指向数组的开头和数组的结尾。 int i_a[8]={0}; int * p_start = &i_a[0]; int *p_end = &i_a[7]; int ret= p_end - p_start ; //int* -int * 结果类型 int 有意义 相差了几个数据元素 。 (0x2000 -x201c) / sizeof(int) printf("ret is %d\n",ret); }

不同类型的指针的解引用操作

如果执行 * 解引用操作话 。 假设指针存储的地址是0x2000 char* ,取0x2000 开始的1个字节空间的数据 int* ,取0x2000 开始的4个字节空间的数据 short* ,取0x2000 开始的2个字节空间的数据 float* ,取0x2000 开始的4个字节空间的数据 double* ,取0x2000 开始的8个字节空间的数据

不同类型的指针的++ ,--

如果执行 ++ 。 假设指针存储的地址是0x2000 char* ,偏移量 1byte -> 0x2001 int* ,偏移量 4byte -> 0x2004 short* ,偏移量 2byte -> 0x2002 float* ,偏移量 4byte -> 0x2004 double* ,偏移量 8byte -> 0x2008

8.内存大小端

对于多字节(大于1字节以上的基本数据类型)的数据在内存中数据存储字节的顺序。
大小端存储方式是由CPU 决定。51单片机,网络设备,都使用大端方式存储数据。AMD,intel,
ARM都是采取小端存储。
小端存储,数据的低位在内存的低地址,数据的高位在内存的高地址
大端存储,数据的低位在内存的高地址,数据的高位在内存的低地址

#include <stdio.h> int main() { int a = 0x12345678; // 强制类型转换 char* p = (char*)&a; // char* = int * // *p 从p指向的首地址开始,偏移量+1(byte) ,取出数据 //printf("val: 0x%x\n",*p); if( 0x78 == *p) { printf("小端存储\n"); } else { printf("大端存储\n"); } return 0; }

http://www.jsqmd.com/news/798603/

相关文章:

  • 物联网产品设计转型:从孤立硬件到系统架构的四大支柱与实战避坑
  • 从ADI收购LTC看电源管理趋势:软件定义电源与能量收集技术解析
  • HTML 结构搭建 (列与卡片)
  • 芯片EOS失效分析与静态电压传播验证方法详解
  • 别再死记硬背了!用一张图+代码片段,彻底搞懂Element UI Menu组件的嵌套关系
  • HandBrake下载安装与视频压缩教程(2026最新版)
  • latex 显示中文 - MKT
  • 从电桥到功放:拆解一个双工对讲机电路,聊聊模拟音频设计的那些门道
  • Everything-Claude-Code 深度解析 —— 给 AI 编程装上 “涡轮增压” 引擎
  • DenseNet的‘特征复用’到底强在哪?用CIFAR-10数据集带你做一次对比实验
  • Unity Mesh优化实战:从顶点压缩到数据剔除的完整指南
  • Windows 国内安装 Claude Code CLI 指南
  • YOLOv11 改进 - 注意力机制 LSKA大核分离卷积注意力:轻量级设计实现动态大感受野,优化小目标检测鲁棒性
  • 超声波实时压接质量检测:从NASA技术看高可靠性连接的无损评估革命
  • 大核小核架构的演进:从DVFS到异构计算,应对先进制程挑战
  • NotebookLM Audio Overview终极指南,覆盖采样率适配、噪声抑制阈值调优、以及语音嵌入向量维度坍缩规避策略
  • 环境准备与构建“脏”数据
  • 【Sora 2视频集成终极指南】:ChatGPT原生调用、API对接、帧级控制与多模态工作流落地实录(2024官方SDK首曝)
  • 暗黑破坏神2存档修改器终极指南:5分钟打造完美游戏角色
  • 5分钟免费解锁iPhone激活锁:applera1n实用指南
  • 告别繁琐槽函数!用C++11 Lambda简化Qt信号连接(附QSlider/QPushButton实例)
  • JScope RTT模式实战:为STM32F4实现最高2MB/s的数据流监控(含代码移植避坑点)
  • Windows三指拖拽终极指南:轻松实现macOS级触控体验
  • 质谱高端访谈Gary Siuzdak
  • 从Distributed到Lumped:三种SPEF寄生模型,你的芯片时序分析该选哪一个?
  • 从学生成绩表到销售报表:手把手教你用ag-grid列组/行组构建复杂业务表格
  • 2026微型变送器十大品牌有哪些,广东犸力小型变送高端优选 - 品牌速递
  • 从PX4的FRD到Mavros的FLU:一文讲透无人机ROS开发中的坐标系‘翻译’逻辑
  • 20254218 2025-2026-2 《Python程序设计》实验3报告
  • Ice:macOS菜单栏终极管理方案,让你的桌面瞬间清爽高效