- 博客(29)
- 资源 (1)
- 收藏
- 关注
原创 STM32教程-01-STM32调试步骤
该图标下面有 6 个选项(下拉选择),我们一般用第一个,也就是逻辑分析窗口(Logic Analyzer),点击即可调出该窗口,通过 SETUP 按钮新建一些 IO 口,就可以观察这些 IO 口的电平变化情况,以多种形式显示出来,比较直观。MDK5 提供 2 个观察窗口(下拉选择),该按钮按下,会弹出一个显示变量的窗口,输入你所想要观察的变量/表达式,即可查看其值,是很常用的一个调试窗口。:通过该按钮,显示调用关系&局部变量窗口,显示当前函数的调用关系和局部变量,方便查看,对分析程序非常有用。
2025-12-23 10:16:58
566
原创 ESP32-Arduino基础-01-GPIO
在微控制器中,GPIO是最常用的外设,即通用输入输出端口GPIO用于写入和读取引脚状态,有的被复用为ADC等等功能。// pin 为数字引脚编号// 比如0 表示GPIO0, 1表示GPIO1// mode 为数字引脚的工作模式// 常用的有// OUTPUT 输出模式// INPUT 输入模式// INPUT_PULLUP 带内部上拉的输入模式// INPUT_PULLDOWN 带内部下拉的输入模式例如:将GPIO1设置为输出模式将GPIO1设置为带内部上拉的输入模式。
2025-12-21 18:05:34
1019
原创 C++ STL之vector类
回顾函数重载x = y;y = tmp;x = y;y = tmp;这段代码展示了 C++ 中的函数重载特性:我们定义了两个swap函数,分别用于交换int类型和float类型的变量。当我们在main函数中传入int类型的x1和y1时,编译器会自动匹配到参数为int&的swap函数;而传入float类型的x2和y2时,则会匹配到参数为float&的版本,从而实现了不同类型变量的交换操作。这里我们使用了 C++中函数重载的特性。
2025-08-25 17:04:36
720
原创 C++手撕vector类代码
此时 pos 虽然还指向原来的内存位置(&v1 [1]),但该位置的元素已经变成了 3——迭代器的 “语义目标”(元素 2)失效了,与你最初的意图完全不符。在常见实现(如 GCC、MSVC)里,vector 迭代器默认直接用 T* 实现,但为了兼容模板、const 语义等,实际会通过 typedef 或嵌套类型封装,本质仍是对指针的 “语义化重命名”。而insert函数会因为扩容,扩容后,形参pos迭代器位置、_start、_finish、_end_of_storage,都不再是之前的数据了。
2025-08-25 17:04:29
1021
原创 C++手撕string类代码
1、_str指针变量:因为是不带参数的默认构造函数,成员变量由构造函数本身通过初始化列表进行初始化,如果对指针变量_str赋给nullptr后,构造函数本身没有问题,但是_str就指向的一个空指针,后续操作带来一系列的问题,所以我们需要将其初始化,通过new一个字节新的char地址,并存放\0,使_str指向一个真正意义的地址,避免后续使用_str指针出现空指针解引用的问题。因为C++ 中类成员变量的初始化顺序由声明顺序决定,而非初始化列表中的顺序,所以必须将成员变量_size的声明放在最前面?
2025-06-30 21:33:50
863
原创 C++ STL之string类
为什么:C++ 标准库中的所有组件(包括string类)都被放置在std命名空间中。int main()// 正确写法,string在std命名空间中// 错误写法,未指定命名空间return 0;
2025-06-30 21:33:45
1234
原创 C++内存管理
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。使用格式:new (place_address) type或者new(place_address) type(initializer - list)place_address必须是一个指针,initializer - list是类型的初始化列表使用场景:定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
2025-06-09 21:43:35
1170
原创 C++模版初阶
函数模版函数模版代表了一个函数家族,该函数模版与类型无关,在使用时被实例化,根据实参类型产生函数的特定类型版本函数模版格式返回值类型 函数名(参数列表){}函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。
2025-06-09 21:43:28
501
原创 C++类和对象(下)
尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表。如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没有显式在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显式在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。无论是否显示写初始化列表,每个构造函数都有其初始化列表无论是否在初始化列表显式初始化成员变量,每个成员变量都要走初始化列表。
2025-05-29 01:15:44
653
2
原创 C++ 类和对象(中)
构造函数:用于初始化对象的成员变量,确保对象在创建时就处于一个合理的初始状态。它的函数名与类名相同,没有返回值。构造函数的本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数⾃动调⽤的特点就完美的替代的了Init。
2025-05-19 20:47:25
995
原创 C++基础
命名空间能够将代码组织到不同的作用域中,从而避免此类冲突。在main函数中,我们需要指定输出的变量rand为命名空间Rand中的变量时,需要在printf(“%d\n”, Rand::rand);解决方法:定义一个新的命名空间,让这个命名空间包含rand这个变量,使rand的变量的作用域在Rand命名空间中,编译器就知道rand是一个变量,而不是生成随机数的函数了。但是在C++中可以使用默认缺省参数这个方法,给函数一个缺省参数,如果函数的实参少了一个参数,仍然可以使用函数的默认缺省参数,将函数运行起来。
2025-05-11 23:42:57
425
原创 C++ 类和对象(上)
在C++中,类是一种用户定义的数据类型,用于封装数据和对数据的操作。类可以包含数据成员(变量)和成员函数(方法),这些成员可以是公有的、私有的或受保护的,以控制对类成员的访问。先看一段程序class Datapublic:_day = day;private:// 为了区分成员变量,⼀般习惯上成员变量// 会加⼀个特殊标识,如_ 或者 m 开头int _year;int _month;int _day;这里我们写了一个日期类。
2025-05-11 23:42:42
979
原创 C++基础-引用
变量本身和它引⽤的变量共⽤同⼀块内存空间。⽐如:⽔壶传中李逵,宋江叫"铁⽜",江湖上⼈称"⿊旋 ⻛";引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间。这里先看一段传址与传引用的例子,因为使用了函数重载,所以两个swap函数因为形参不同,所以可以同时存在。这2个简单的例子都说明了传引用调用的便捷之处,减少了传地址调用后,程序更容易理解了。再看引用的第二种大的用法,被调函数返回堆区变量别名,而不是返回变量的拷贝。引用的第一个大的用法,做为形参,减少使用传地址调用。
2025-04-21 00:58:34
181
原创 C语言数据结构-堆(基于完全二叉树)
所以在AdjustUp函数中,函数的第一个形参是数组,第二个形参是新插入数据的数组下标,通过公式(i-1)/2的方式取得父结点的数组下标,并与其进行比较,如果子结点小于父结点,则互相交换位置,依次比较到根节点,保证如果新插入的数据如果比堆中的原有数值都要小,也能到达根结点。在向堆内插入数据的时候,不像顺序表直接在数组size的位置直接插入数据即可,因为我们设计的大堆或者小堆,在插入数据后,我们需要保持堆的特性,而不是直接插入数据,那样无法保持大堆或者小堆的特性了。若i=0,i为根节点编号,无父结点。
2025-04-10 21:09:18
1245
原创 C语言数据结构-顺序表
情况2:当pos的位置是在ps->size,此方法就是尾插程序,因为for循环中i=ps->size-1,而for循环的判断程序是 i>= ps->size,而ps->size-1是永远不会大于ps->size的,导致for循环不成立,直接进入下一条语句,ps->arr[pos] = x,对arr数组size的位置进行赋值,所以就是尾插。而尾删的方法,数组最后一个元素的下标是ps->size-1,这与for循环的判断条件冲突,所以for循环不执行,直接执行ps->size--,与尾删的方法相同。
2025-03-17 14:37:33
796
原创 C语言编写扫雷游戏
seed的中文意为种子,可以理解为基于这个种子产生随机数的,如果不设置seed的话,srand默认使用1为seed,导致每次生成的随机数都是相同的,为了让srand函数每次都产生一个不同的随机数,我们每次调用srand函数的时候,都需要输入一个不同的seed,防止随机数相同。mine是一个二维数组,用于存放雷的坐标,因为为了防止在排查用户输入坐标周围的雷的数量时越界,二维数组必须必实际显示的坐标要大一圈,即实际上二维数组为11*11大小,而显示时只显示行列下标1-9的范围,简而言之这个数组是后台计算用的。
2025-03-10 19:09:25
1017
原创 C语言程序的编译与链接
1、左图为条件编译指令,#ifdef MAX的意义为如果定义了MAX宏,那么执行最近的哪个#endif之间的程序,因为之前已经定义了MAX宏,所以在 #ifdef 和 #endif之间的程序通过了条件编译,并在右图test.i上显示了出来。然后我们在命令行中运行 gcc -E test.c -o test.i ,这句命令行的意思是用gcc 预处理(-E) test.c这个文件,并输出为(-o) test.i。(1)预处理:展开头文件/宏替换/去掉注释/条件编译 test.i。(4)链接: 生成可执行文件。
2025-03-10 00:50:01
372
原创 C语言文件操作基础
数据文件:文件的内容不一定是程序,而是程序运行中需要保存的数据,比如一个通讯录程序,我们输入的数据,在程序结束后,自动输出为一个.txt文件,下次启动通讯录程序,会直接加载我们已经数据的数据。而每个被使用的文件都会在内存中开辟一个相应的文件信息区,用来保存文件信息,这些文件信息保存在一个结构体变量中,这个结构体是由系统直接进行声明的,名字叫做FILE。我们使用文件指针去维护文件,间接对文件进行操作,注意是间接操作文件,不是直接操作文件的,这点需要注意。.txt是文件后缀,表示这是一个txt文件。
2025-03-09 23:33:15
449
原创 C语言结构体声明使用和对齐
1、什么是自定义类型,int,char,short,double,float就是类型。自定义类型就是自己定义的类型。4、结构体对齐,非常重要。结构体属于自定义类型。
2025-03-01 23:56:30
195
原创 C语言指针基础-1
int 表示指针指向一个int类型的数据,*表示后面的pa是指针变量,pa是这个指针变量的名字。答:&a就是取出a在内存中的地址,在X86系统中a的大小为4个字节,即4*8=32bit。刚才已经说了,pa中存放的是a的地址,那么通过a的地址是不是能找到a呢?这个代码的意思就是通过存放在pa里a的地址,并将地址解引用为a。可以理解为*pa等于a,那么*pa = 10,就等于a = 10;定义一个int*型指针变量pa,并将其初始化为a的地址,即&a。4、解引用操作符* 和取地址操作符 & 的关系。
2025-02-20 22:46:01
227
原创 C语言结构体
数组:一些值的集合,要求类型是一致的,如int arr[10],arr数组中是10个int类型的数据。此处定义了一个类型为:struct Book 的结构体,注意他的类型就是是 struct Book。并用struct Book类型定义了b4 b5 b6这3个struct Book类型的变量。与其对应的是C语言编译系统自带的类型如:int、double、float、char等。结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量。结构:一些值的结合,不要求类型是一致的。
2024-12-02 16:39:41
199
1
原创 C语言学习心得-二维数组
就像一个n的元素的一维数组一样,数组下标从0开始,到下表n-1结束,即元素个数-1。从上面的程序可以看出,与一维数组一样,二维数组在内存中也是连续存放的。所以这个arr[3][5]其实是由3个包含5个元素的一维数组组成的。即从arr[3][5]中第一个一维数组arr[0]依次高地址递增。实际上意味着这个二维数组包含3个一维数组,每个一维数组都包含5个。1、定义一个二维3行5列的二维数组,将其数组元素全部置为0。是第一个一维数组,包含元素。是第二个一维数组,包含元素。是第三个一维数组,包含元素。
2024-08-12 19:53:30
306
原创 C语言学习心得-一维数组
显然此处中sizeof(arr)中的arr肯定不是数组的地址,要不sizeof(地址),是没有意义的 ,所以此处的arr代表的是整个元素所占用的内存空间,所以sizeof(arr)代表的arr数组所占用内存空间的大小,而sizeof(arr[0])表示数组元素的大小,所以sizeof(arr) / sizeof(arr[0])即可以求出数组元素数量10.2、数组名arr单独写的时候,对应着arr数组的首地址,与&arr[0]是一致的,&即取地址符号,这个后面会详细说,是比较绕人的一个部分。
2024-08-12 19:15:21
1007
原创 C语言学习心得-break、continue用法
如果程序中if语句后是continue时,当循环到i==5时,跳过continue后面的语句printf函数,取消一次打印,再次进入循环体,直到for循环条件判断满足结束。break跳出的是本级循环,本级循环即为while循环,不是跳过if选择语句后面的程序,再次进入循环,而是直接跳出整个while循环体,执行return 0语句。判读i不等于5,跳过if语句,执行输出 1,后i++,i== 2,以此类推。判读i不等于5,跳过if语句,执行输出 1,后i++,i== 2,以此类推。(一)break用法。
2024-08-06 14:41:42
827
原创 C语言学习心得-do-while循环
2、假设输入num 为11,是个两位数,i++,i==1,11/ 10 == 1,进入条件判断表达式(1)即(真),再次循环i++,i==2,1/10==0,进入条件判断表达式(0)即(假),退出循环,打印i=1,即输入数为两位数。1、假设输入num 为1,是个一位数,1 / 10 == 0,进入条件判断表达式(0)即(假),退出循环,打印i=1,即输入数为一位数。打印10,接着i++,i==11,此时条件判断表达式 i<=10,不满足,退出循环。再次进入循环体,输出2,i++,i==3....
2024-08-06 14:19:30
392
原创 C语言学习心得-while循环
但是while语句不会跳转,只要括号内的n>2这个条件成立,就会一直打印“hehe”,直到退出程序。所以需要()内的条件控制语句来实现while语句的结束,如条件表达式中始终为真的话,就一直执行循环体中的内容。然后num 除以10,因为num是一个整数,整数的除法不保留小数,所以123/10=12;然后num 除以10,因为num是一个整数,整数的除法不保留小数,所以12/10=1。然后num 除以10,因为num是一个整数,整数的除法不保留小数,所以1/10=0。1 > 0,为真,进入下次循环。
2024-08-06 13:54:03
323
原创 关于C语言分支语句的学习心得-关系操作符
由于在写程序时,常常因为失误将==等于操作符写为 = ,所以在常量和一个变量比较大小时,将常量放在 == 的左边,防止少写一个 = ,变为赋值运算符。如果:month >= 3 为假 ,那么即使不判断 Month <= 5 整个表达式的结果也为0,所以右侧的month<=5就不在计算了。如果:month == 12 即使不计算后续的month == 1和month == 2 整个表达式的结果也为1。例如: if(month == 12 || month == 1 || month == 2)
2024-08-05 17:15:10
648
1
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅