目录
一、长度查询类
二、比较类
三、复制/填充类
四、连接/拼接类
五、查找/搜索类
六、转换类
七、实用工具类
八、STM32 常用技巧与陷阱
1. 避免的函数
2. 安全替代方案
3. 内存对齐与 Flash 字符串
4. RTOS 环境下的重入问题
5. Newlib 配置优化
九、quick reference 速查表
在 STM32 开发中,字符串操作主要依赖标准 C 库 <string.h> 和 <stdio.h> 中的函数。由于资源受限,通常需注意内存消耗、重入性和缓冲区安全。
一、长度查询类
| 函数 |
原型 |
用途 |
STM32 注意点 |
strlen |
size_t strlen(const char *s); |
返回字符串长度(不含 \0) |
空指针、越界风险 |
strnlen |
size_t strnlen(const char *s, size_t maxlen); |
限制最大长度的 strlen |
STM32 推荐,防无限读取 |
// 示例:安全获取长度
size_t len = strnlen(buf, sizeof(buf) - 1);
二、比较类
| 函数 |
原型 |
用途 |
STM32 注意点 |
strcmp |
int strcmp(const char *s1, const char *s2); |
逐字符比较(区分大小写) |
返回 0 表示相等 |
strncmp |
int strncmp(const char *s1, const char *s2, size_t n); |
比较前 n 个字符 |
STM32 推荐,防溢出 |
strcasecmp |
int strcasecmp(const char *s1, const char *s2); |
不区分大小写比较 |
部分库支持(Newlib 有) |
// 示例:安全比较命令
if (strncmp(cmd, "AT+", 3) == 0) { /* ... */ }
三、复制/填充类
| 函数 |
原型 |
用途 |
STM32 注意点 |
strcpy |
char *strcpy(char *dest, const char *src); |
复制字符串(含 \0) |
❌ 危险!无边界检查 |
strncpy |
char *strncpy(char *dest, const char *src, size_t n); |
复制最多 n 个字符 |
必用,但需手动补 \0 |
memcpy |
void *memcpy(void *dest, const void *src, size_t n); |
内存块复制(不关心 \0) |
STM32 高频使用,效率高 |
memset |
void *memset(void *s, int c, size_t n); |
内存块设置 |
常用于清空缓冲区 |
// 推荐写法:strncpy + 强制终止
char buf[32];
strncpy(buf, src, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0'; // 确保终止
四、连接/拼接类
| 函数 |
原型 |
用途 |
STM32 注意点 |
strcat |
char *strcat(char *dest, const char *src); |
拼接字符串 |
❌ 极易溢出 |
strncat |
char *strncat(char *dest, const char *src, size_t n); |
最多拼接 n 个字符 |
需先确保 dest 有剩余空间 |
snprintf |
int snprintf(char *s, size_t n, const char *fmt, ...); |
格式化拼接(推荐) |
C99 标准,STM32 常用 |
// Roson 推荐:snprintf 组合字符串(安全且灵活)
char msg[64];
int len = snprintf(msg, sizeof(msg), "TEMP:%d,HUM:%d", temp, hum);
五、查找/搜索类
| 函数 |
原型 |
用途 |
STM32 注意点 |
strchr |
char *strchr(const char *s, int c); |
查找字符首次出现 |
返回 NULL 表示未找到 |
strrchr |
char *strrchr(const char *s, int c); |
查找字符最后一次出现 |
常用于取文件扩展名 |
strstr |
char *strstr(const char *haystack, const char *needle); |
查找子串 |
无则返回 NULL |
strpbrk |
char *strpbrk(const char *s, const char *accept); |
查找第一个出现在accept集合的字符 |
常用于分隔符解析 |
// 示例:查找 AT 命令返回值中的 "\r\n"
char *p = strstr(buf, "\r\n");
六、转换类
| 函数 |
原型 |
用途 |
STM32 注意点 |
atoi |
int atoi(const char *nptr); |
字符串转 int |
无错误处理,不推荐 |
atol |
long atol(const char *nptr); |
字符串转 long |
同上 |
strtol |
long strtol(const char *nptr, char **endptr, int base); |
推荐,支持进制转换 |
可检测转换错误 |
sprintf |
int sprintf(char *s, const char *fmt, ...); |
格式化输出到字符串 |
❌ 无边界检查,危险 |
snprintf |
int snprintf(char *s, size_t n, ...); |
安全版 sprintf |
STM32 必备 |
// 推荐:strtol 转换(带错误检查)
char *end;
long val = strtol(str, &end, 10);
if (*end != '\0') { /* 转换不完整 */ }
七、实用工具类
| 函数 |
原型 |
用途 |
STM32 场景 |
strtok |
char *strtok(char *str, const char *delim); |
按分隔符切分字符串 |
解析 AT 命令、JSON 字段 |
strspn |
size_t strspn(const char *s, const char *accept); |
返回接受字符集的跨度 |
跳过前导空白/固定头 |
strcspn |
size_t strcspn(const char *s, const char *reject); |
返回排斥字符集的跨度 |
同上 |
memchr |
void *memchr(const void *s, int c, size_t n); |
内存中查找字符 |
适用于二进制+文本混合 |
// 示例:解析 CSV
char *token = strtok(line, ",");
while (token) {
process(token);
token = strtok(NULL, ",");
}
八、STM32 常用技巧与陷阱
1. 避免的函数
// 危险!ST 标准库可能不检查边界
strcpy(dest, src); // ❌ 禁止
strcat(dest, src); // ❌ 禁止
sprintf(buf, "%s", str); // ❌ 禁止(溢出风险)
2. 安全替代方案
// 安全拷贝
strncpy(dest, src, sizeof(dest)-1);
dest[sizeof(dest)-1] = '\0';
// 安全格式化(STM32 强烈推荐)
snprintf(buf, sizeof(buf), "%.2f", voltage);
3. 内存对齐与 Flash 字符串
// STM32 中,字符串字面量通常在 Flash(.rodata)
// 如需放入 RAM,使用 PROGMEM 等效方案(HAL 库无,需自定义)
// 示例:RAM 中的 const 字符串
const char cmd_ok[] = "OK\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)cmd_ok, strlen(cmd_ok), 100);
4. RTOS 环境下的重入问题
// 自由RTOS下:strtok 不是线程安全的!
// 使用 strtok_r(GNU 扩展)或自行实现
char *strtok_r(char *str, const char *delim, char **saveptr);
5. Newlib 配置优化
STM32 HAL 默认使用 Newlib 或 Newlib-nano,可在 syscalls.c 中实现轻量版 _sbrk、_write 后,字符串函数体积可控。
九、quick reference 速查表
// 最常用组合(STM32 推荐)
strlen() → 长度(优先 strnlen)
strncmp() → 安全比较
memcpy() → 块复制(最快)
snprintf() → 格式化输出(代替 sprintf)
strstr() → 子串搜索
strtok_r() → 线程安全切分
strtol() → 带错误检查的数值转换
总结: STM32 下字符串处理的核心原则是:优先 strn 族、摒弃 str 无边界函数、强制用 snprintf、配合 RTOS 时注意重入性。**
所有评论(0)