嵌入式c学习七
c语言指针:程序需要载入内存中运行,在32bit系统中内存地址的范围是:0x0000 0000-0xFFFF FFFF,内存大小为4GB,内存地址指的是内存单元的编号是固定的,本身就是一个整数,对于32bit系统,内存地址对应的编号是4字节的正整数
地址:c语言规定用户有权对对内存地址进行命名,地址编号本身也可以当初数据存在变量中
指针:c语言规定,用户打算定义一个变量来存储地址,则在定义变量前需要指明,变量中存的是一个地址,存储地址的变量叫做指针变量,指针变量定义格式:数据类型 *变量名;如int *p ==>p是变量名,*修饰变量p表示p是一个指针即p里面存储的数据是一个地址 ==> int 表示p指向的地址的内存下面的数据是整型
空指针:对指针变量初始化需要吧指针变量里面对应的内存设置为0,需要吧0强制转换成地址
0x00000000 ==> (void *)0x00000000 == c语言提供了宏定义NULL
保留区:linux系统的内存中有一部分内存是保留区,地址范围为:0x0000 0000-0x0804 8000,此区域用户无法访问,一旦访问就会出现段错误

int *p = NULL; //对指针变量进行初始化,目的是防止野指针出现,避免段错误
#include <stdio.h>int main()
{int data = 20;int *p = NULL; //对指针进行初始化,避免野指针出现p = &data; //p ==> &p ==> *(&p) == p,使用变量是操作系统默认先找到变量的地址(&),在间接访问地址里面的数据(*) //通过变量名访问 data = 10;printf("data: %d\n", data); //10*(&data) = 20;printf("data: %d\n", data); //20 data == *(&data)//通过指针访问*p = 40;printf("data: %d\n", data); //40 p = &data ==> *p == *(&data) return 0;
}

保留区地址用户是无法访问的,但可以定义指针指向这块空间,指针变量只能存储这个地址,不能间接访问该地址下的值,否则会段错误(Segmentation fault)
数组指针:int b[5]; int *p = b;
#include <stdio.h>int main()
{int a[5] = {1,2,3,4,5};for(int i=0; i<5; i++){printf("a[%d]=%d ", i, a[i]); }printf("\n");int *p = a; //此处a表示数组首元素地址,即a==&a[0] //通过数组下标访问a[0] = 10;printf("a[0]=%d\n", a[0]); //10//通过指针访问*(p+1) = 20; printf("*(p+1)=%d\n", a[1]); //20 p == a ==> *(p+1) ==*(a+1) == a[1]return 0;
}

地址的运算:一般只能对地址进行 +- 运算,表示地址的偏移,偏移的单位取决于该地址下存储的数据的类型
#include <stdio.h>int main()
{int a[5] = {1,2,3,4,5};printf("a的地址为: %p\n", a); //a表示数组首元素地址 printf("a+1的地址为: %p\n", a+1); //a+1表示地址向后偏移一个数组元素单位即4字节 printf("&a+1的地址为: %p\n", &a+1); //&a表示 整个数组地址,&a+1表示地址向后偏移一个数组单位即4*5=20字节 int *ptr = (int*)(&a+1); printf("*(a+1)=%d\n", *(a+1)); //2 *(a+1) = a[1] = 2printf("*(ptr-1)=%d\n", *(ptr-1)); //5 return 0;
}

二维数组与指针
#include <stdio.h>int main()
{int aa[2][5] = {{1,2,3,4,5},{6,7,8,9,10}};//单独从地址的值来说,aa==aa[0]==&aa[0][0]==&aa printf("aa地址 %p\naa[0]地址 %p\naa[0][0]地址%p\n&aa地址 %p\n", aa, aa[0], &aa[0][0], &aa); //aa表示数组首元素地址,即aa == &aa[0]printf("&aa[0]的地址: %p\naa的地址: %p\n", &aa[0], aa); printf("aa+1的地址: %p\n", aa+1); //aa+1表示地址从aa[0]偏移到aa[1],偏移aa[2]数组中一个元素的字节:4*5=20字节 printf("&aa的地址: %p\n\n", &aa); //&aa表示整个数组的地址printf("&aa+1的地址: %p\n\n", &aa+1); //&aa+1,表示地址向后偏移一个数组单位即2*4*5=40字节 int *ptr1 = (int*)(&aa +1); //此时ptr1指向数组aa的后一个地址 printf("*(ptr1-1)=%d\n", *(ptr1-1)); //10 向后偏移一个整型元素aa[1][4]的值 int *ptr2 = (int*)(*(aa+1)); //此时ptr2表示aa[1]的地址,int*表示指向aa[1][0] printf("*(ptr2-1)=%d\n", *(ptr2-1)); // 5 aa[0][4] return 0;
}

二维数组的访问
#include <stdio.h>int main()
{int aa[2][5] = {{1,2,3,4,5},{6,7,8,9,10}};for(int i=0; i<2; i++){for(int j=0; j<5; j++){printf("aa[%d][%d]=%d ", i, j, aa[i][j]);}printf("\n");}//p变量名,*p表示p是指针,[5]表示p指向有5个元素的匿名数组,int表示指针指向的内存中数据为整型 int (*p)[5] = aa; //将数组aa的首地址即&aa[0]存到指针变量p中//数组下标访问aa[0][0] = 10; // aa[0][0] == *(aa[0]+0) == *aa[0] == *(&aa[0][0])printf("a[0][0]=%d\n", aa[0][0]); //指针变量访问aa[1][2]//aa[1][2] == *(aa[1]+2) == *(*(aa+1)+2) ==>aa==&aa[0]==p ==>*(*(p+1)+2) *(*(p+1)+2) = 80;printf("a[1][2]=%d\n", aa[1][2]); return 0;
}

指针数组:数组中每个元素都是指针,定义格式:数据类型 *数组名[元素个数];如:int *p[5];
二级指针:指针变量中存储的值,是另一个指针变量的地址
指针与数组的定义:int * (*p)[3][4]
p:表示变量p
*p:表示变量p是一个指针,用于存放地址
[3]:表示指针p存储的地址下的数据类型是一个匿名数组,可以存放三个元素
[4]:表示匿名数组[3]中每个元素都是一个有4个元素的匿名数组
*: 表示匿名数组[4]中每个元素的类型是一个指针
int:表示[4]中存储的指针所指向的地址是int
int *(*p)[2][3]; //运算符优先级()>[]>* // *p :表示p是一个指针存放的数据是地址// (*p)[2] :表示p指针里面存放的地址,地址下面的数据类型为匿名数组[2]里面有两个元素// (*p)[2][3] :表示匿名数组[2]里面的数据,类型是匿名数组[3]->里面有三个元素// *(*p)[2][3] :表示匿名数组[3]里面的数据,类型是指针// int *(*p)[2][3]:表示匿名数组[3]里面存的地址,地址所下面存的数据类型为int
二级指针定义格式:int data; int *p1= &data; int **p2 = &p1;==>*p2是一个指针存储的值为地址,*表示p1里面存的地址下面的值,还是指针
#include <stdio.h>int main()
{int data = 10; //定义整型变量 int *p1 = &data; //定义指针变量存储data的地址 int **p2 = &p1; //定义二级指针,存储指针p1的地址 //用变量名访问数据data = 20;printf("data=%d\n", data); //用指针p1访问数据*p1 = 30; //p1==&data ==>*p1 == *(&data) == data printf("*p1=%d\n", data); //用指针p2访问 **p2 = 40; //p2 == &p1 ==> *p2 == *(&p1) == p1 ==> **p2 ==*p1 == dataprintf("**p2=%d\n", data); //一维数组形式访问p1[0] = 50; //p1[0] == *(p1+0) == *p1 == data printf("p1[0]=%d\n", data); //二维数组形式访问p2[0][0] = 60; // p2[0][0] == *(p2[0]+0) == *p2[0] == *(*(p2+0)) == **p2 == data printf("p2[0][0]=%d\n", data); return 0;
}

练习:
#include <stdio.h>int main()
{int buf[5] = {1,2,3,4,5};int *p = buf;printf("%d\n", *p++); //1:++后置,*p =buf[0]=1,结束后P指向a[1]的地址 printf("%d\n", (*p)++); //2:++后置,*p=buf[1]=2,结束后p指向a[2]的地址 return 0;
}
![]()
相关文章:
嵌入式c学习七
c语言指针:程序需要载入内存中运行,在32bit系统中内存地址的范围是:0x0000 0000-0xFFFF FFFF,内存大小为4GB,内存地址指的是内存单元的编号是固定的,本身就是一个整数,对于32bit系统,…...
Selenium Web UI自动化测试:从入门到实战
引言 在当今快速迭代的软件开发周期中,自动化测试已成为保障产品质量、提升测试效率的核心手段之一。而针对Web应用的UI自动化测试,Selenium作为最流行的开源工具之一,凭借其跨浏览器、多语言支持(Python、Java、C#等)…...
【实战指南】用MongoDB存储文档和图片等大文件(Java实现)
一、前言 在现代应用开发中,经常需要处理和存储大量的文档、图片等大文件。传统的关系型数据库在处理这类大文件时,往往会面临性能瓶颈、存储成本高等问题。而 MongoDB 作为一款流行的 NoSQL 数据库,提供了 GridFS 规范,能够很好地解决大文件存储的问题。GridFS 可以将大文…...
Jetpack Compose 显示时间
Jetpack Compose 显示时间 介绍主体代码使用 介绍 在软件中实时显示时间 主体代码 import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStat…...
vue3中,通过获取路由上的token直接进入首页,跳过登录页面
1.需求 A系统想快速进入到B系统,但又不想输入账号密码,A系统的token与B系统共用token,因此在访问B系统就会在路径上携带token(https://magictool-box.com/login?token《token》),通过token直接进入B系统首…...
软考通关利器:中级软件设计师结构化开发核心考点
简介: 作为国家软考中级认证的核心科目,“软件设计师” 结构化开发能力是职业进阶的黄金敲门砖。本模块聚焦考试大纲高频考点,深度解析需求建模、结构化分析方法(SA/SD)、模块设计原则、数据流图(DFD&#…...
[思考记录]两则:宏观视角、理想化
#宏观视角# 昨天听金老师讲解了他初步整理的大模型宏观概念关系图,受益不少。图上不仅是涵盖了诸多概念,更厉害的应该在于把概念之间的关系进行了描述,更直观展现了概念是如何与其他概念相互作用的。帮助从整体的角度去理解,以及透…...
MySQL 性能优化方向
MySQL 性能优化是一个系统性的工作,涉及数据库设计、查询优化、索引优化、硬件配置等多个方面。以下是 MySQL 性能优化的主要方向和具体优化方案: 一、数据库设计优化 1. 合理设计表结构 规范化设计:避免数据冗余,确保数据一致性。适度反规范化:在查询频繁的场景下,适当…...
3-22 vector的使用详解---STL C++
C中的vector容器展开系统讲解,具体内容如下: 1. vector的定义和特性(基础概念) 讲解vector作为动态数组的核心特性:自动内存管理、动态扩容机制(倍增策略)对比普通数组:支持随机访…...
Collectors.toList / list 转 list
前言 略 Collectors.toList List<User> userList ...; List<Long> userIdList userList.stream().map(User::getUserId).collect(Collectors.toList());...
uniapp 和 webview 之间的通信
1.背景 应用使用了uniapp开发跨端应用,在uniapp中内嵌webview页面实现页面热更新效果,不需要用户单独重新安装软件即可实现页面的版本更新。 2.webview通知uniapp 在开发过程中我们难会遇到需要uniapp和webview来实现数据通信的场景,接下来…...
【Linux】Hadoop-3.4.1的伪分布式集群的初步配置
配置步骤 一、检查环境 JDK # 目前还是 JDK8 最适合 Hadoop java -version echo $JAVA_HOME Hadoop hadoop version echo $HADOOP_HOME 二、配置SSH免密登录 Hadoop需要通过SSH管理节点(即使在伪分布式模式下) sudo apt install openssh-server …...
【Java】深入了解下Java Bitset
【Java】深入了解下Java Bitset 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战 目录 【Java】深入了解下Java Bitset引言如果Java Bitset不是布尔数组,那它是什么…...
Linux CentOS7 安装 ffmpeg教程
官网:FFmpeg 操作 先用uname -a 查看内核版本,如果是 3.2.0或者以上就可以按照此办法来安装 cd /tmp wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz# 2. 解压 tar xvf ffmpeg-release-amd64-static.tar.xz# 3. 将…...
楼宇自控系统的结构密码:总线与分布式结构方式的差异与应用
在现代建筑中,为了实现高效、智能的管理,楼宇自控系统变得越来越重要。它就像建筑的 智能管家,可自动控制照明、空调、通风等各种机电设备,让建筑运行更顺畅,还能节省能源成本。而在楼宇自控系统里,有两种关…...
Fourier-Lerobot——把斯坦福人形动作策略iDP3封装进了Lerobot(含我司七月人形研发落地实践)
前言 近期在抠lerobot源码时,看到其封装了ALOHA ACT、diffusion policy、π0时,我就在想,lerobot其实可以再封装下idp3 我甚至考虑是否从我联合带的那十几个具身研究生中选几个同学做下这事,对他们也是很好的历练然当25年3.18日…...
系统架构设计知识体系总结
1.技术选型 1.什么是技术选型? 技术选型是指评估和选择在项目或系统开发中使用的最合适的技术和工具的过程。这涉及考虑基于其能力、特性、与项目需求的兼容性、可扩展性、性能、维护和其他因素的各种可用选项。技术选型的目标是确定与项目目标相符合、能够有效解…...
计划管理工具应该具备的能(甘特图)
在当今快节奏的项目管理环境中,高效地规划和跟踪项目进度是至关重要的。甘特图,作为项目管理领域的经典工具,以其直观的时间轴和任务分配方式,深受项目管理者的青睐。 随着数字化时代的到来,甘特图线上编辑器应运而生&…...
简单实用!百度AI + Raphael AI = 免费生图
简单实用!百度AI Raphael AI 免费生图 --  第一步:下载或截取一些好看的图片当参考图片 第二步:用百度AI描述你想要的图片&…...
2 相交链表
1 常规思路 比较两个链表的长度,然后让较短的链表走二者长度之差,此时两个链表就一样长了,开始用双指针遍历,如果有相等返回,没有返回null; 为了减少冗余代码,我们设置一个minCur和maxCur分别…...
2025-03-22 学习记录--C/C++-C 库函数 - getchar()
C 库函数 - getchar() ⭐️ C 标准库 - <stdio.h> (一)、函数声明 🍭 int getchar(void)从标准输入 stdin 获取一个字符(一个无符号字符)。 参数:🎀 NA 返回值:Ἰ…...
APM 仿真遥控指南
地面站开发了一段时间了,由于没有硬件,所以一直在 APM 模拟器中验证。我们已经实现了 MAVLink 消息接收和解析,显示无人机状态,给无人机发送消息,实现一键起飞,飞往指定地点,降落,返…...
如何防止大语言模型生成有害内容?技术与非技术手段解析
目录 如何防止大语言模型生成有害内容?技术与非技术手段解析 1. 技术手段 方法 1:使用内容过滤(Content Filtering) 方法 2:基于模型的有害内容检测(Toxicity Classification) 方法 3&#…...
BBR 和 CUBIC 对长肥管道的不同反应
有个关于 CUBIC(等一众 AIMD-based cc) 和 BBR 在长肥管道中的行为比较挺有趣,它们的表现竟然截然相反: CUBIC 流共存,RTT 越大,Goodput 越低;BBR 流共存,RTT 越大,Goodput 越高。 前一个被看…...
架构师面试(十九):IM 架构
问题 IM 系统从架构模式上包括 【介绍人模式】和 【代理人模式】。介绍人模式也叫直连模式,消息收发不需要服务端的参与,即客户端之间直连的方式;代理人模式也叫中转模式,消息收发需要服务端进行中转。 下面关于这两类模式描述的…...
Spring框架入门指南:从Hello World到IOC容器
第一章:Spring框架的介绍 1. Spring框架的概述 Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。 Spring是于2003 年兴起的一个轻量级的Java开发框架&…...
嵌入式电路设计软件个人安装步骤分享
各位小伙伴大家好,今天给大家分享一个,电路设计软件的安装方法,希望对大家有所帮助。 一、下载【Multisim14.0安装包】: 链接:夸克网盘分享 提取码:kHSP 电脑安装Multisim14.0并且汉化 准备安装包以及汉化包双击“NI_Circuit_Design_Suite_14_0【海量免费资源:kebaiwan…...
git | 回退版本 并保存当前修改到stash,在进行整合。[git checkout | git stash 等方法 ]
目录 一些常见命令: git 回退版本 一、临时回退(不会修改历史,可随时回到当前版本) 方法1:git checkout HEAD~1 二、永久回退(改变分支指向) 方法2:git reset 1. 保留修改&am…...
学习笔记:黑马程序员JavaWeb开发教程(2025.3.22)
11.1 案例-员工管理-新增员工 考试完之后,时隔一个月再次运行项目,出现了报错: class lombok.javac.apt.LombokProcessor (in unnamed module 0x5d7f1e59) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironme…...
Java IO性能优化:字节流与缓冲流的对比与实战分析
引言 在Java开发中,文件读写和网络数据传输是高频操作。然而,许多开发者在使用FileInputStream、FileOutputStream等基础字节流时,常因忽略IO性能问题导致程序效率低下。本文将深入分析普通字节流与**缓冲字节流(BufferedInputSt…...
