![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C/C++
灵哎惹,凌沃敏
“任何一个傻瓜都能写出计算机可以理解的代码,唯有写出人类容易理解的代码,才是优秀的程序员。”
展开
-
MDK/keil高阶使用手册
MDK/keil的一些高阶使用技巧,很有用原创 2024-05-10 15:49:24 · 570 阅读 · 0 评论 -
记录一个GD32E230的ADC+DMA的重大问题
经过各种研究都没发现问题:正常和不正常情况下ADC和DMA的寄存器值都是一样的,内存也没有越界访问;确认flash读写函数无问题;而且最离谱的是,有的时候开机是正常的,有的时候是异常的,也就说是同一个程序有的时候启动正常,有的时候异常;虽然最后发现了问题,但是也没发现问题,因为还是没搞懂为啥会跟flash读写有关,更没有搞懂为啥同一个程序有时启动就没问题有时就有问题!,即7个通道的数据位置错了,原本1通道的数据到了5通道,5通道的到了3通道!把这一句注释掉了就再也不会出问题了~原创 2024-04-26 11:37:46 · 383 阅读 · 0 评论 -
C/C++提高代码稳定性/健壮性的一些小细节
对于C/C++编程本来就是要摸透两大块,一个是编译器,另一个是相应处理器的内核和外设的知识和特性,这其中编译器是比较容易被忽视的原创 2024-03-29 10:07:58 · 522 阅读 · 0 评论 -
C/C++与汇编交互总结
并且在C中调用汇编函数时可以传入参数,需要传入哪些参数和参数类型只要在extern时声明下就可;也可以有返回值,存在R0或R0-R1中,但是。如果该C函数有传递参数的,则在调用前把参数赋值到R0-R4即可;若有返回值的,则调用后从R0或者R0-R1(返回值为64位)读取即可;2.汇编当中可以引用C全局变量,也是"IMPORT"一下即可,如上例;引用进来的是该变量的地址,不是变量的值。当有返回值时,汇编函数中在退出前需要将返回值赋值给R0或R0-R1。4.C当中也可以使用汇编的标号,用法还是先。原创 2024-02-18 18:39:19 · 759 阅读 · 0 评论 -
ARM/CM3/CM4:读写内核寄存器和内核特殊寄存器
可以发现每一个函数都用到了“ldr r0,=core_res_c”这句话,这句话可以非常神奇的将core_res_c全局变量的地址传递给内核寄存器,就相当于建立了一个C和汇编直接数据传输的通道,我们就可以借助这个通道对内核寄存器进行读写了,当然这个通道的存在是借助于编译器的,所以文章第一句话就声明了和编译器的瓜葛。注:以下代码涉及内联汇编,所以跟C编译器有关,有些编译器可能会不支持(每种编译器内联汇编的形式都不一样),本代码在MDK的“defaul compiler version 6”编译器里测试通过。原创 2024-01-29 15:07:52 · 625 阅读 · 0 评论 -
记录一个Cortex-M23的一个重要问题
对于Cortex-M23,它要求按照字访问的内存,其访问地址必须是字(4字节)对齐的,否则就进入Hard_fault原创 2023-09-22 16:36:01 · 457 阅读 · 0 评论 -
面向过程和面向对象编程详解
面向对象是把跟要处理的事情相关的所有事物封装成一个对象,每个对象内有各种属性、行为(函数)和变量,然后用这些对象的属性、行为、变量去完成事情;所有高级语言都是面向对象的或者说能够面向对象编程的,然后几乎所有高级语言都是在C的基础上发展起来的,所以说面向对象编程是正确的编程语言发展方向,是大势所趋,因为面向过程更符合机器的思维(机器就是想让你告诉他一步一步该怎么做),而面向过程更符合人类的思维,而编程语言的发展肯定是要让人类更加方便快速的编程,所以发展面向对象编程是理所应当的。原创 2023-03-10 17:23:21 · 184 阅读 · 0 评论 -
git学习记录/菜鸟教程(基于Gitcode)
本文章记录了从零开始使用git的操作原创 2023-02-28 15:53:20 · 701 阅读 · 0 评论 -
关于强制转换数据类型后再存储或发送是否会影响数据字节顺序不一致问题
强制类型转换与数据大小端问题原创 2022-12-07 17:59:33 · 242 阅读 · 0 评论 -
GCC编译输出中text,data,bss和dec的含义
bss是不会算入最终生成的bin文件里面的,因为对于未初始化的变量,只需要在内存中开辟个相应大小的空间就行了。2.data:已初始化的全局/静态变量,相当于MDK的rw_data。3.bss:未初始化的全局/静态变量,相当于MDK的ZI_DATA。1.text:代码和常量,相当于MDK的code+ro_data。4.dec:上述3者的算术和。原创 2022-09-08 22:37:49 · 2766 阅读 · 0 评论 -
visual c++:error LNK2019: 无法解析的外部符号 __imp....
visual studio;c++;error LNK2019原创 2022-05-30 15:34:19 · 998 阅读 · 0 评论 -
Windows环境变量是啥
环境变量代表的就是一个文件夹路径,即用一个变量代表一个路径,类似C/C++的宏定义。 环境变量有两种:系统环境变量(简称系统变量)和用户环境变量(简称环境变量),顾名思义,系统环境变量不区分用户,作用于所有用户;用户环境变量只作用于当前用户。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序...原创 2022-04-21 14:53:56 · 2549 阅读 · 0 评论 -
内联函数简介与作用
简介 在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。设计内联函数的动机 ...转载 2022-03-08 15:59:43 · 548 阅读 · 0 评论 -
关于C/C++宏定义/预编译
1.宏定义在函数内部和外部是一样的(都视为在外部),所以一般不把宏定义放在函数内部以免造成误导;如果一个函数里面只有宏定义 那么该函数相当于不存在。2.在一个文件或者多个文件中重复定义一个标志编译不会报错,有的编译器会出警告。3.预编译时对宏定义的处理就是简单的替换,如果说涉及标志重定义的,那么替换时就以最新宏定义为准,关于这点下面作详细说明:假设现在有a.c,a.h,b.c,b.h四个文件:1.先在a.h中定义testdef为20,再在b.h中定义testdef为30,然后在a.c中先包含原创 2022-01-07 18:14:07 · 1318 阅读 · 0 评论 -
关于C与C++区别的摘录
1.博主:恒虚之境作者:恒虚之境链接:https://www.zhihu.com/question/28834538/answer/477487776来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。大家都知道,上古时代,猿猴用机器代码写程序,而且好像还是01二进制编码的表现方式。这些01代码精确表达了计算机CPU所要做的每一个动作(每一条指令)从内存的某个地址中读数到寄存器中,寄存器中又再做那些事情,动作完了之后,又将运算结果送回内存,程序计数器跳转到那个位置.转载 2021-12-23 18:11:12 · 141 阅读 · 0 评论 -
记录:程序跳转前一定要先禁止所有中断
之前在做程序更新时,有发现程序跳转后莫名出现执行异常或卡死问题,后面百般调试发现如果跳转前禁止所有中断的话就好了,但是不知道具体为什么; 今天看到个大神写的文章才知道,原来是在程序跳转后,并且在新程序的__main函数执行之后(该函数负责初始化新程序的内存)并在新程序的SCB->VTOR执行之前刚好发生中断了,而中断中用到的变量的地址刚好和新程序的内存使用空间重合,这样就导致新程序的内存被篡改,导致程序运行不正常或卡死。...原创 2021-12-23 10:30:28 · 373 阅读 · 0 评论 -
记录:HAL释义
HAL:Hardware Abstraction Layer,硬件抽象层硬件抽象层技术最初是由Microsoft公司为确保WindowsNT的稳定性和兼容性而提出的。针对过去Windows系列操作系统经常出现的系统死机或崩溃等现象,Microsoft总结发现,程序设计直接与硬件通信,是造成系统不稳定的主要原因。在得出这个结论的基础上,微软公司在WindowsNT上取消了对硬件的直接访问,首先提出了硬件抽象层(Hardware Abstraction Layer,简称HAL)的概念,硬件抽象层就是:“将硬原创 2021-12-23 10:21:53 · 1777 阅读 · 0 评论 -
从函数指针到回调函数
函数指针:指向函数的指针,某个函数指针表示指向某一类型函数的指针。我们知道,指针类型有整型、浮点型、字符型等,现在又加了一种类型:函数型;浮点型指针就叫浮点指针,那么函数型指针就叫函数指针;我们既然可以把浮点指针当做函数的传递参数,那么自然也可以把函数指针当做函数的传参,函数A在其传参中带有函数指针类型一般是为回调函数做准备的,在调用函数A时被传递进去的函数(如B)我们一般称之为回调函数。那么为什么函数A要带有一个函数指针类型,弄得这么复杂呢,那是因为写函数A的人(如写系统的人)不确定其他人原创 2021-12-09 22:02:35 · 161 阅读 · 0 评论 -
关于VSCode编码:自动猜测编码字符集
VSCode有自动猜测打开文件的编码的功能,设置如下:点击 文件->首选项->设置搜索设置处搜索“编码”图中红框处打钩即可.原创 2021-08-24 16:24:45 · 1893 阅读 · 0 评论 -
FreeRTOS任务调度
1.FreeRTOS内核支持抢占式调度和时间片轮转调度,默认情况下时间片轮转调度是使能了的,抢占式调度需要用户在FreeRTOSConfig.h中自己使能(configUSE_PREEMPTION)2.抢占式调度用于不同优先级的任务之间,时间片轮转调度用于同优先级任务之间3.有且只有以下5种情况会触发任务切换: 1.有比当前运行任务更高优先级的任务进入了就绪态 2.当前运行任务调用了阻塞函数(如vTaskDelay、等待任务通知、等待信号量等)使自己进入了阻塞态,...原创 2021-07-19 16:52:20 · 928 阅读 · 0 评论 -
Free-RTOS删除当前任务/自己删除自己
使用:vTaskDelete(NULL),但是要注意调用vTaskDelete(NULL)之后任务就在当前语句停止了,其后面的代码不会再被执行。原创 2021-07-19 15:34:04 · 1607 阅读 · 0 评论 -
关于FFT精华/精简详解
1.对一段离散数据(N个点,比如说AD采样值)的FFT结果就是这N个点对应的复数 a+bi;2.假设采样频率为Fs,点数为N,则本次FFT的频率分辨率为FS/N,即FFT结果d原创 2021-06-09 10:49:01 · 1857 阅读 · 0 评论 -
总结:Unicode、GBK、UTF-8之间的区别
Unicode:所有字符都是两个字节,对于英文字符,高字节为0,低字节与ASCII码相同GBK:中文字符为两个字节;英文字符为1个字节,且与ASCII码相同。原创 2021-06-05 15:06:15 · 4252 阅读 · 0 评论 -
C/C++ 在宏定义字符串中引用宏定义
需求:现有字符串A,B,C都包含字符串D,如:#define stra "123/456/789"#define strb "111/222/789"#define strc "333/444/789"#define strd "789"以上是对这种情况的最简单粗暴的实现方式,这种方式的缺点就是每次strd改变的时候(如从"789"变成"abc")就需要替换所有的"789",那么有没有其他方式可以不用重复写"789"呢:方式1:#define stra原创 2021-04-06 16:32:20 · 2765 阅读 · 0 评论 -
关于cJSON_Delete导致程序各处free都失败的原因
原因:如果程序中有删除父级的cJSON,则不用在删除父级的cJSON之前删除子级的cJSON了,否则会导致内存分配紊乱(大量free的入口地址找不到),从而导致后续所有的free都失败。 比如,json2是json1的子级,则如果有删除json1的代码就不用了再删除json2了,否则内存紊乱。...原创 2021-03-31 18:51:51 · 2554 阅读 · 2 评论 -
记录:从一个函数里向另一个函数传递参数要用指针变量,不能用局部非指针变量
如题,从A函数中调用B函数向C函数传递参数,传递完A函数会结束时不能用局部非指针变量,因为局部非指针变量在函数结束后会被回收的,这回导致传递过去的参数为空;但是局部指针变量是malloc在堆区的,要主动free才会消失; 所以,此时要注意的是,在C函数中用完该指针变量后要记得free掉,否则造成内存泄漏!...原创 2021-03-26 10:40:58 · 243 阅读 · 0 评论 -
fatfs如何判断一个文件的打开关闭状态
为了防止重复关闭一个文件,我们在关闭之前需要判断该文件是否已经打开:1.在f_close函数中加入对文件指针fp中的文件大小成员清零的代码:2.然后就可以通过判断此成员是否为0来获知该文件是否打开了:...原创 2021-02-03 10:47:44 · 1269 阅读 · 0 评论 -
关于C/C++编译时明明包含了某头文件,却仍然提示该头文件中的某类型未定义
问题原因:在A.h中包含了B.h,B.h中包含了C.h,然后C.h中包含了A.h,这样就相当于A.h自己包含了自己,然后在编译A.h时(确切的说应该是编译包含A.h的c文件时)A.h就会被展开两次,第二次展开的时候就会报错。解决:不在C.h中包含A.h,编译通过总结:其它出现这种问题的肯定都是因为在复杂的头文件包含关系中出现自己包含自己的情况...原创 2020-12-30 10:34:47 · 17581 阅读 · 4 评论 -
STM32(ARM)核心知识记录
1.malloc和free函数是由C库实现,然后MDK做了适配,这就解释了为什么malloc函数知道堆区在哪里(为什么它能准确的在堆区申请内存)。2.当程序中没有使用到malloc时堆区是不起作用的,此时MDK会将其省略,也就你Heap_Size设置多大都不起作用。3.当函数的传递参数少于4个且总长度不大于16字节时,编译器会采用R0-R3来传递,不需要入栈出栈,也就不需要访问内存,提高速度。4.C的函数名能代表函数的起始地址,这点和汇编的label是一样的。...原创 2020-10-12 16:21:39 · 250 阅读 · 0 评论 -
ARM:导出汇编中的标志在C中使用
比如对于STM32,导出其栈底(注意是栈底)地址: EXPORT Stack_Mem //EXPORT前面一定要加Tab键,否则编译报错然后在C中extern: extern void Stack_Mem(void);然后就可以使用了,比如将其赋值给一个int型变量,然后打印出来:int k;k=(int)Stack_Mem;printf("k=%d\n",k);...原创 2020-10-12 15:57:12 · 275 阅读 · 0 评论 -
C/C++ 往指定地址读写的三种方式
嵌入式编程中免不了要往指定地址读/写数据,如配置各种外设时需要写外设的寄存器,下面我总结了三种读写指定地址的方式:我们这次准备使用的是STM32F4的串口3的数据寄存器:USART3->DR,地址0x40004804;1.使用强制转换: 写:*(u16*)0x40004804=0x55; 读:u16 k=0; k=*(u16*)0x40004804;C/C++的强制转换是一个非常重要的知识点,学好了可以为你的编程带来很大的方便,以上就是使用强制转换将数字0x40...原创 2020-09-14 14:50:12 · 7947 阅读 · 1 评论 -
数据存储的大小端格式问题记录
大小端定义:大端格式:即数据的高位存在低地址,如0x11223344,在存储器中从低到高的存储顺序就是0x11,0x22,0x33,0x44小端格式:即数据的高位存在高地址,如0x11223344,在存储器中从低到高的存储顺序就是0x44,0x33,0x22,0x11大端格式会更好理解一点,因为它是顺序的;小端格式会需要转换一下。STM32的内存和flash都是按照小端格式存储的。如何判别大小端:1.判别RAM的大小端方法1:定义一个32位变量,给其赋值0x11223344,再定原创 2020-09-08 13:59:01 · 1404 阅读 · 0 评论