1. 类型 & 字节转换
char short int
-
智能家居:网关协议,mac地址、ip地址、端口号上报
-
智慧农业:温湿度采集,小数点数据上传云平台
float temp = 38.6;
char *ip = "192.168.1.1";
char temp_array[2] = { 38, 6 };
char ip_array[4] = { 192, 168, 1, 1 };
typedef unsigned char unit8;
typedef unsigned char unit16;
typedef unsigned char unit32;
时间戳举例:
#include <stdio.h>
typedef unsigned char unc;
typedef unsigned int unit;
// 66C8 6B78
unc time_buf[4] = { 0x66, 0xC8, 0x6B, 0x78 };
unit time;
unit u8Tou32B(unc* buffer)
{
return (((((((unit)buffer[0]) << 8)
| buffer[1]) << 8)
| buffer[2]) << 8)
| buffer[3];
}
int main()
{
time = u8Tou32B(time_buf);
printf("time = %ld s\n", time);
}
2. if & switch
前者用于两种状态情况下或者某个范围内,后者用于多状态配合枚举更加直观。
-
智能家居:控制灯的开关
-
智能音箱:网络连接状态
typedef enum
{
NET_INIT = 0,
NET_CONNECTING,
NET_CONNECT_SUCCESS,
NET_CONNECT_FAIL,
NET_ERROR,
} E_NET_STATUS;
int main()
{
E_NET_STATUS net_status;
switch (/* expression */)
{
case /* constant-expression */:
/* code */
break;
default:
break;
}
}
3. for & while
两者可以互换,保持某种特定条件循环建议使用后者。
-
自动售卖机: 判断是否存在待处理订单
-
智能音箱:打印当前搜索到的wifi信息
-
自动售卖机:判断当前所以订单的金额(有收入有退币 )
#include <stdio.h>
int main()
{
int status;
while(status == true )
{
// 存在订单
}
int wifi_array[20] = { 0 };
int count = sizeof(wifi_array) / sizeof(*wifi_array);
for (int i = 0; i < count; i++)
{
// 打印
}
}
4. static
控制变量的存储方式和作用范围以及管理生命周期。
-
点餐屏:统计损耗使用次数
#include <stdio.h> void Used() { static int used = 0; printf("used:%d\n", (used ++) + 1); } int main() { for(int i = 0; i < 5; i++) { Used(); } }
5. #define
强大且无敌的替换。
-
代码中定义测试与发布版本
-
定义某个特定功能的开关
常见用法:
#define APPID "123456"
#define PI 3.14
#define MAX_LEN (100 + 1)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SWAP(a, b) do { \
int t = 0; \
t = a; \
a = b; \
b = t; \
} while(e)
//将一个字母转换为大写
#define UPCASE(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c))
//判断字符是不是18进值的数字
#define DECCHK(c) ((c) >= '0' && (c) <= '9')
//防止溢出的一个方法
#define INC_SAT(val) (val = ((va1) + 1 > (val)) ? (val) + 1 : (val))
//返回数组元素的个数
#define ARR_SIZE(a) (sizeof((a)) / sizeof((a[0])))
#define CONNECT(a,b) a##b
#define TOCHAR(a) @#a
#define TOSTRING(a) #a
用来定义测试与发布版本以及日志信息:
#include <stdio.h>
#define VERSION_PRE 1
// #define VERSION_GOLD 1
#define LOG_OPEN 1
int main()
{
#ifdef LOG_OPEN
printf("just1n.cn\n");
#ifdef VERSION_PRE
printf("PRE__VERSION__ \n");
// todo
#elif VERSION_GOLD
printf("GOLD__VERSION__ \n");
// todo
#endif
#endif
}
6. strcut
具有相同类型或不同类型的数据构成的数据集合。
-
自动售货机:设备所有资源管理(设备状态、网络状态、电机状态、传感器状态、订单状态等)
#include <stdio.h> typedef struct { int num; int time; int money; } T_Pay; typedef struct { int used; int time; int id; } T_Manager; typedef struct { int system_status; int net_status; int motor_status[4]; int pay_status; T_Pay m_Pay; T_Manager m_Manager; void* (statusCallbackfunc)(); } T_Device; int main() { T_Device g_Device_1; }
7. 指针 *
变量为了表示数据而生,指针为了传递数据为生。
- 智能音箱:音频处理
#include <stdio.h>
void pcmSpeex(char *data)
{
//TODO
}
int main()
{
char pcm_data_char;
char pcm_data_arrary[4096];
pcmSpeex(&pcm_data_char);
pcmSpeex(pcm_data_arrary);
}
8. 回调函数
通过函数指针来调用的函数,观察者模式,事件模型。
-
送餐机器人:底盘移动到目标位置后,通知应用程序
-
智能音箱:网络状态改变后,通知应用程序
传统方式:
-
开放变量,让别人直接获取
-
通过getStatus()类似的函数定时获取
#include <stdio.h>
// 工具代码
typedef struct
{
int status;
void (*statusChange)();
} T_Device;
T_Device g_Device;
void addCallbackFunc(void (*pstatusChange)(int status))
{
g_Device.statusChange = pstatusChange;
}
int getStatus()
{
return g_Device.status;
}
void run()
{
g_Device.status = 10;
if(g_Device.status == 10)
{
if(g_Device.statusChange != NULL)
{
g_Device.statusChange(g_Device.status);
}
}
}
// 用户代码
void callBack(int status)
{
printf("callBack: status = %d\n", status);
}
int main()
{
// for(;;)
// {
// int status = getStatus();
// }
addCallbackFunc(callBack);
run();
}
回调的重点在于获取这个实时变化的值不是由我本身去获取,而是把获取后的操作方法告诉数据拥有者,让拥有者自己去获取并且处理数据,而我只是提供一个方法。
9. 其它场景:数据拷贝和动态内存分配
例如智能音箱进行配网时,获取到网络列表后,进行过滤,写出过滤函数。
- malloc 裸机不建议使用,带操作系统的可以
- freertos 实现类内存管理池
- Linux 有内存管理的模块(实际访问映射表、不直接访问硬件地址)
void handleWifiList(const char *plistdata, int len)
{
char *mdata = (char *)malloc(len);
memcpy(mdata, plistdata, len);
// 业务处理 ....
free(m_data);
}
我要是有你这样的学习效率就好了啊啊啊啊啊点评完毕哈哈你真棒
领导莅临?