
C/C++
文章平均质量分 63
猪哥-嵌入式
这个作者很懒,什么都没留下…
展开
-
LwIP系列(6):TCP client 连接服务器3次握手代码流程简单分析
在上一篇文章中,我们详细描述了TCP 3次握手、4次挥手、状态机转换,本文从lwip的代码维度,分析下tcp client的发起连接的流程,之所以单独分析tcp client,是因为嵌入式设备,client使用场景较多。原创 2023-08-15 22:34:38 · 731 阅读 · 0 评论 -
hashmap哈希map是什么?什么时候需要使用hashmap?C实现hashmap示例
对于C程序员,尤其是嵌入式C程序员,hashmap使用的相对较少,所以会略显陌生,hashmap其实涉及到2个概念,分别是哈希(hash)、map。哈希hash:是把任意长度输入通过蓝列算法变换成固定长度的输出,这种转换是一种压缩映射,一般不可逆。这是专业的解释,我们常说的crc16、crc32、lrc、md5、sha256等,本质上都是哈希hash,只不过散列算法不同而已。原创 2022-12-25 22:04:21 · 1962 阅读 · 0 评论 -
RTOS系列文章(9):再次分析栈帧、函数调用与中断调用的区别
在前面的系列文章中,尤其是CM3/4之LR寄存器、EXC_RETURN深入分析 中我们简单的分析了一些函数调用与中断调用的流程,那篇文章也基本上能说明函数调用和中断调用的一些区别,本文将基于栈帧的概念,再次分析一下两者之间的相同点和不通点。栈帧是一个非常专业的概念,很惭愧的说,在没有深入分析RTOS之前,我也不曾了解栈帧这一概念,之前只是大概了解到函数调用需要堆栈存放局部、临时变量,但是栈帧这个概念确实时从未关注过。我们先引入《The Definitive guide to ARM Cortex M3/4》原创 2022-06-06 22:03:24 · 1761 阅读 · 2 评论 -
RTOS系列文章(8):深入分析中断处理过程
在上一篇文章中,我们深入分析了函数调用返回、中断调用返回使用的LR和EXC_TURN,也简单说明了函数调用流程、中断调用流程。在FreeRTOS中,任务的调度是通过SysTick + PendSV 中断来实现的,尤其在PenSV中断中进行任务上下文切换原理,是理解FreeRTOS任务调度原理的重中之重。而SysTick和PendSV都是中断,所以我们有必要深入分析一下在ARM CM3/4中中断的完整处理流程。整体流程如下:接下来我们直接引用《The definitive guide to ARM Corte原创 2022-06-04 22:54:10 · 4440 阅读 · 3 评论 -
RTOS系列文章(5):C语言程序运行原理分析:汇编、栈、栈帧、进栈、出栈、保存现场、恢复现场、返回
C源程序; Reset handlerReset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0原创 2022-05-28 19:10:46 · 3743 阅读 · 1 评论 -
一个非常好的各种算法动画图演示网站
http://www.u396.com/wp-content/collection/data-structure-visualizations/原创 2022-04-23 22:19:57 · 2535 阅读 · 0 评论 -
AliOS Things代码风格
原地址AliOS Things代码风格1. 前言本文是AliOS Things提供的一套C语言代码规范,适用的对象为符合C99标准的C语言工程。2. 命名本节内容均为建议,不作强制要求。2.1. 总则各种命名均使用英文单词及其缩写,非特殊情况不能使用汉语拼音或其他语言。2.2. 文件命名文件名全部使用小写字母,用_连接。源文件使用.c后缀。头文件使用.h后缀。2.3. 类型命名2.3.1. 简单类型命名使用typedef自定义的简单类型命名全部使用小写字母,用_连接,以_t结尾。转载 2022-04-23 18:52:00 · 246 阅读 · 0 评论 -
int、long、long int、long long、uint64_t字节长度
前言我们在进行编程时,对于int、long、long long经常使用,但是对于这些类型占用的字节长度可能不会太确定,尤其是在32位平台、64位平台,会有差异,这些知识点为基础知识,容易忽略的基础知识,本文做下分析记录。不同平台整型字节长度区别平台/类型charshortintlonglong long16位1224832位1244864位12488小结在32位平台下,int型和long型是一致的,都是占用4个字节。lo原创 2021-12-19 22:26:01 · 72280 阅读 · 2 评论 -
C语言函数参数:一级指针、二级指针的应用小结
在之前的文章 《二级指针的作为函数形参的深入理解》 我们分析了二级指针的使用,这里我们再简单的的做个小结。一级指针作为入参一级指针作为入参,在函数内部是要对该指针进行 简介引用,操作一级指针指向的内存,也就是这个入参的是直接 引用和修改的。不能作为 内存地址返回。 ,如果想要返回一个地址,可以直接让函数进行返回。// 错误 -- 指针是[传值调用]int func(char *p){ char *a = malloc(10*sizeof(char)); p = a; // 指针是传值调用原创 2021-10-24 18:39:19 · 2786 阅读 · 0 评论 -
字符串转数字函数 atol、atoll和strtol、strtoll、strtoul、strtoull 分析
前言在C/C++编程中,经常会遇到将字符串转换成数值的场景需求,其实在C标准库中已经给我们提供了很多功能函数。常用字符串转数值函数列表头文件#include <stdlib.h>ato-x函数名称含义相似功能函数double atof(const char *nptr)将字符串转换成double值strtod(nptr, NULL)int atoi(const char *nptr)将字符串转换成int值strtol(nptr, NULL, 10原创 2021-07-25 22:02:58 · 8102 阅读 · 2 评论 -
内存泄露和内存溢出的区别
前言对于程序员来讲,这是两个学术性的概念,虽然大多数人都会遇到,可能叫不上名字。内存泄露Memory Leak:指程序在申请内存后,用完后,没有释放。通俗解释1: 用完内存扔了,没有归还。通俗解释2: 甲向乙借了100万,花完,没有还。内存溢出Memory Overflow:指程序申请内存时,没有足够的内存共申请者使用。通俗解释1: 霸占了不属于你的资源。通俗解释2: 甲向乙借1000万,但是乙只有100万。...原创 2021-07-23 14:17:29 · 242 阅读 · 0 评论 -
__sprintf_chk’ may write a terminating nul past the end of the destination [-Wformat-overflow=]报警解决
在使用sprintf时,编译时会检测格式化输出的缓存大小,如果缓存过小,则会出现该警告,比如代码如下就会出现这样的警告void func(int cnt){ char buf[10]; sprintf(buf, "%d", cnt); // ....}解决办法:只需要将buf的大小改大即可,如下:char buf[32];...原创 2020-12-05 19:36:27 · 7434 阅读 · 0 评论 -
sprintf、snprintf、vsprintf、vsnprintf格式化函数分析
格式化输入、可变参数表格式化输入。原创 2020-05-29 10:42:04 · 5807 阅读 · 0 评论 -
数组的优点就是链表的缺点,链表的优点就是数组的缺点
本文的标题是无意中看到的一句话,是(qq_37839971)对某篇文章的回复,这句话可能不太严谨,但是概括性很强,概括了数组和链表数据结构的部分优缺点,数组是一种顺序存储线性表,最大的优点是可以快速的存取表中任一位置元素,而缺点就是表长度不够灵活,而且想要插入、删除操作时,需要移动大量的元素。链表数据结构可以说是一种有强关联的数据结构,表长度灵活,可以随时增加删除,插入或删除操作也不需要移动太多...原创 2020-05-04 22:17:10 · 451 阅读 · 0 评论 -
使用C 实现的 开源消息队列 cQueue
</>概述队列是一种非常好用的数据结构,消息队列可以提高业务逻辑的成功率,在Unix/Linux下,消息队列还是进程之间通信的一种技术方案,关于队列数据结构的知识点,可以参考之前的文章:深入理解数据结构(一):队列队列的功能虽然很好用,但是如何编写一个文件的消息队列功能,还是有些难度的,本文参考uC/OS 操作系统的队列代码原理,编写了消息队列 功能,使用者可以将cQueue....原创 2020-05-03 21:30:19 · 5246 阅读 · 0 评论 -
调用free 后内存状态
malloc和free是常用的动态内存申请和释放函数,功能就不赘述了,尤其在调用 free 后,我们脑海中想到的就是释放之前申请的内存区域,那么我们再细究一下,调用free(p) 后,指针p值和 p指向的内存状态是什么样呢?说下答案吧:1、调用free(p) 后,p值不变。2、调用free(p) 后,p指向的内存的值不确定,有可能变,也有可能不变。这里就说明了一个容易忽略的结果...原创 2020-05-03 19:07:44 · 1733 阅读 · 0 评论 -
单向链表删除并清空操作 注意
在之前的文章《深入理解Linux内核之链表 list.h 功能实现原理、接口说明及示例代码》中详细的分析了链表的各种操作,我们经常使用的操作是“初始化”、“ 添加节点”、“遍历”、“删除”,对于链表节点的删除,使用的相对少,而且由于 删除操作的 宏函数 定义的复杂,容易混淆,本文基于此,对 链表的删除清空做下备忘录。以单向链表结构 为例,用到的宏函数有2个,分别为:/* * I...原创 2019-12-27 18:23:34 · 2286 阅读 · 0 评论 -
ID 值自动 “申请”和“释放” 算法及C代码 (2)
在上一篇文章《ID值自动申请和释放》中,简单的介绍下应用背景和C代码,不过上一篇中的代码 至适用于 “释放”一次,不支持多次释放,也就是说必须要释放1次后,下一次操作必须是重新申请,因为代码中没有 使用 “队列”操作,所以本文为了实现多次释放的功能,进一步改善了代码,引入了队列的思想,关于“队列”的概念,可以参考之前的文章《深入理解数据结构(一):队列 及 C代码框架》。下面就是具体的代码:#...原创 2019-11-03 19:51:54 · 457 阅读 · 0 评论 -
ID 值自动 “申请”和“释放” 小算法及C代码
简单的说下题目中涉及到的 应用场景,在 开发 网关或一些组态软件的时候,我们一般是需要创建变量或者设备表的,还有就是对于数据库表中的 ID值,我们在对表中记录进行“增”、“删”操作时,也涉及到 ID值的 管理,这个具体体现为:(1)当我们新创建一个变量或一条记录时,希望ID值为最新的,而且是唯一的、递增的。(2)如果只有“增”操作,没有“减”操作,那就比较简单了,对id值进行 id...原创 2019-11-02 18:52:53 · 616 阅读 · 0 评论 -
return命令--后面的程序不执行
C或C++语言中有一个return命令,该命令很容易忽略1项功能,即return为函数结束符,如果函数中运行到return命令后,除了返回值,该函数也将运行结束,后面如果有程序也将不再运行,不过也不用担心这一点,后面程序不运行的前提是要运行到return命令,因为有些if判断,是不运行对应分支的return命令的。原创 2016-01-05 11:00:51 · 6252 阅读 · 0 评论 -
cJSON的简单使用——STM32移植
目录背景知识 JSON数据结构cJSON重要接口函数解析案例移植注意 事项背景知识 JSON是一种轻量级的数据交换格式,这里不做详细的分析,简单的理解为,是互联网上的一种数据打包协议,比较方便人阅读和编写,下面是阿里云物联网设备影子信息的json格式,如下所示:{ "state": { "reported": { "hz": ...原创 2019-06-10 14:48:23 · 7795 阅读 · 2 评论 -
二级指针的作为函数形参的深入理解
在上一篇文章《C函数的“传值调用”和“传址调用”的深入分析》我们分析了函数参数的使用,对于一级指针,理解起来相对容易,而二级指针参数的理解相对难一些,我们先说一下二级指针作为函数形参的目的。 二级指针作为形参,往往是为了获取一个特定“地址”,没错,就是想要通过形参获取地址。这里可能会有些疑问,如果想要获取地址,那么直接将函数 返回值设定为指针型就可以啊,这 当然是可以的,但是还有一...原创 2019-07-15 22:15:03 · 7353 阅读 · 1 评论 -
指针的使用注意事项:空指针、指针赋值、void *指针
前面的文章,分析了指针的一些概念,可以说指针是C的灵魂,看起来简单,但是想要理解透彻却是相当难,需要大量的练习,不断的巩固,不断的重复才能尽可能的理解指针,这里做一个简单的阶段总结。1、指针是地址,而不是具体的标量值,这是指针的精髓,不管是一级指针、二级 指针、 整型指针、浮点数指针、结构体指针等等等等所有类型的指针,内容都是个地址,而指针本身当然也是有地址的,而且容易忽略的是,不管这...原创 2019-07-21 21:07:53 · 5189 阅读 · 0 评论 -
命令行参数小结
说来惭愧,对于命令行参数这个概念接触的比较少,可能也是之前一直使用IDE进行开发程序的原因吧,对于C程序,总是从main函数开始执行,main函数的原型如下:int main(int argc, char *argv[]);这里面我们可以发现main函数的特点:(1)有两个形参,argc和 argv。(2)返回值为 int,有符号整型,我们常常在main函数的最后,添加 ...原创 2019-08-31 16:16:45 · 626 阅读 · 0 评论 -
cJSON打包功能使用-代码案例、特别注意事项
在前面的文章《cJSON的简单使用——STM32移植》中,分析了cJSON的简单使用和移植步骤,这个使用 案例主要 是针对 json包解析的,其实cJSON也提供 json 包 打包 功能,这里针对常用的“对象”类型json进行打包,我们主要使用到以下几个接口函数:1、cJSON *cJSON_CreateObject(void) 该函数用于 创建1个 objec...原创 2019-09-07 22:22:44 · 2166 阅读 · 0 评论 -
cJSON库使用:特别注意事项
cJSON的简单使用——STM32移植cJSON打包功能使用-代码案例、特别注意事项 在前面的文章中,我们对cJSON进行了一些简单分析,包括解析、打包这两种最常用功能,cJSON的移植相对简单,但是在使用的时候,还是有一些特别需要注意的地方的,这 主要是因为 cJSON库 中的一些函数会进行内存申请操作,但是并不会自动释放内存,这就相当于 是风险, 需要使用者自己去及时的释放 内存。...原创 2019-09-07 22:32:55 · 3807 阅读 · 0 评论 -
Unix编程艺术:哲学基础
目录阐述一:阐述二阐述三:1、模块原则。2、清晰原则。3、组合原则.4、分离原则:策略同机制分离,接口同引擎分离。5、简洁原则:设计要简洁,复杂度能低则低。6、吝啬原则:除非确无 它法,不要编写庞大的程序。7、透明性原则:设计要可见,以便 审查和调试。8、健壮原则:健壮源于透明与简洁。9、表示原则。10、通俗原则:接口设计 避免标新立异...原创 2019-09-09 20:54:23 · 627 阅读 · 0 评论 -
C语言 枚举enum 知识点总结
目录1、枚举中的值是整型。2、枚举中的成员就是一个全局“宏”。3、如果第1个枚举成员未赋值,第一个枚举成员默认值为整型的0。4、没有指定值的枚举元素,其值为前一元素加1.5、枚举元素的值可以自定义,也可以不定义。 枚举类型在C编程中经常用到,尤其是状态枚举、使得程序的可读性更强,“枚举”正如字面意思,将变量可能 出现的值都列举出来,限定变量的值范围,比如:...原创 2019-09-19 22:21:15 · 3268 阅读 · 0 评论 -
C语言 带参数宏定义中 # 和 ## 知识点总结、代码分析
目录一、宏定义中 “#”知识点1、直接转换字符串,不展开。2、转换出的结果一定是“字符串”。二、宏定义中 ## 知识点1、应用场景2、“##”的作用是将 左右两边的参数做整体字符串拼接替换3、经过 ## 替换后的内容必须 有一个 同名的 变量与之对应。4、 只拼接,不展开。5、## 操作 动态函数指针 案例代码一、宏定义中 “#”知识点 #的...原创 2019-09-21 21:26:46 · 3522 阅读 · 0 评论 -
C函数的“传值调用”和“传址调用”的深入分析
目录传值调用传址调用指针参数的妙用 C中函数一般都有形参,当然也有形参为void的函数,对于那些有形参的函数,我们在调用的时候,就涉及到参数的传递,我们常见的参数有2种,一种是标准变量参数,比如int、char、结构体等单独变量,另一种就是指针,指针可以是一级指针,也可以是多级指针。传值调用 对于上面说的第1种,函数的参数是标量参数,我们在调用函数,给函数传递参...原创 2019-06-19 22:12:50 · 1716 阅读 · 0 评论 -
C的指针的理解
简单看完《C和指针》这本书后,感慨颇多,最大的感觉就是为什么没有早点看这本书,我们在学校里学的教材,太基础了,等到工作后,尤其是看到程序员大牛和一些优秀开源项目时,总会很纳闷儿?他们的代码为什么能这么写,为什么显得好高级啊,直到看完C和指针这本书,才发现,原来答案都在这里面,真是有种,“课堂学的不考,课下学的才考”的感受。 指针是C语言的灵魂,起码我是这么认为的,为什么这么说呢?...原创 2019-06-09 22:12:33 · 461 阅读 · 0 评论 -
CPU执行程序的简单理解
本文引用了《CPU执行程序的原理(简化过程)》、《CPU的运行到函数调用做个了解》部分图片和内容,这里向作者致谢。 这里不去讲过于专业的专业知识,毕竟,CPU上的任意一个知识点,想讲明白,都不容易,我们从使用者的角度去分析,CPU执行程序的过程原理。目录一、背景知识简单介绍1、CPU系统图2、RAM3、ROM4、指令二、程序运行基本流程知识延伸:函...原创 2019-06-07 22:00:26 · 5233 阅读 · 0 评论 -
volatile 关键字作用
volatile-英文翻译为:挥发性的,不稳定的,反复无常,或者说反复变化的。volatile的产生,说到底与编译器的一种技术有关,这种技术叫做“数据流分析”,编译器会先优化分析程序中的变量在哪里赋值,在哪里使用,在哪里失效,分析结果会用于常量合并,进一步消除死代码,CPU运行时,变量时有2个地方使用的,一个是寄存器,可以理解为硬件,另一个为RAM,RAM中的变量会经常的被赋值变化,而寄存器中原创 2017-08-07 16:39:02 · 507 阅读 · 0 评论 -
static 关键字用法
在C或C++中,static主要用作定义全局静态变量、定义局部静态变量、定义静态函数。所谓“静态”,打个比方就是,告诉编译器:“我想静静的做个美男子”,给我在内存中一席之地,我在我自己所在的作用域(C文件)中,从一而终(进程开始到结束),别人休想打扰我(别的文件不能直接调用他),即便外部有很多跟我同名同姓的也无所谓,因为我的名字不会出现在江湖(不是严格的全局变量)。、使用场景1-定义全局静原创 2017-08-07 16:21:15 · 381 阅读 · 0 评论 -
一维条形码CODE128编码及字符集CODE A、B、C解析
在进行一维条形码打印的编程中知道了条形码有一种类型是code128,也是比较常用的,具体的字符集有3种,分别为A、B、C,这三种的说明如下:A格式:数字、大写字母和控制字符组成的字符串,如ABC、ABC123B格式:数字、大小写字母和字符组成的字符串,如Abc123、a-123(B)C格式:双位数字组成的字符串,如1234、00008182。一般来说,如果条幅内容是大写英文字母,用原创 2017-07-21 10:19:39 · 22785 阅读 · 0 评论 -
一种全局变量的定义方法
参考uCOS中的全局变量定义,下面的方法很巧妙:在XXX.h头文件中定义如下#ifdef XXX_GLOBALS#define XXX_EXT#else XXX_EXT extern 然后再XXX.C文件中声明#define XXX_GLOBALS这样做有一个好处,在XXX.C文件中如果使用这些变量,由于已经宏定义了XXX_GLOBALS原创 2017-06-07 10:38:33 · 729 阅读 · 0 评论 -
嵌入式C编程的几个基础
1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情:1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计转载 2017-04-27 17:40:34 · 1026 阅读 · 0 评论 -
堆和栈的区别
一、预备知识—程序的内存分配 一个由C/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其 操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回 收 。注意它与数据结构中的堆是两转载 2017-04-05 10:37:14 · 338 阅读 · 0 评论 -
error: #77-D: this declaration has no storage class or type specifier
在使用Keil编写程序时,无意间发现一个特别简单也是特别容易忽略的问题,编译报错如下:error: #77-D: this declaration has no storage class or type specifier按照错误指向,发现了对应的程序行非常简单,(真实的程序是先定义结构体,然后再对结构体进行赋值),这里等效简化,程序如下://////////////int a原创 2015-12-01 17:22:17 · 45947 阅读 · 1 评论 -
C++之虚函数
引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。class Cman{public:virtual void Eat(){……};void Move();private:};class CChild : public CMan{public:virtual void Eat(){……};private:};CMan m转载 2015-11-16 15:18:28 · 410 阅读 · 0 评论