C 语言字符串库函数(STM32 常用整理)
目录一、长度查询类二、比较类三、复制/填充类四、连接/拼接类五、查找/搜索类六、转换类七、实用工具类八、STM32 常用技巧与陷阱1. 避免的函数2. 安全替代方案3. 内存对齐与 Flash 字符串4. RTOS 环境下的重入问题5. Newlib 配置优化九、quick reference 速查表在 STM32 开发中字符串操作主要依赖标准 C 库string.h和stdio.h中的函数。由于资源受限通常需注意内存消耗、重入性和缓冲区安全。一、长度查询类函数原型用途STM32 注意点strlensize_t strlen(const char *s);返回字符串长度不含\0空指针、越界风险strnlensize_t strnlen(const char *s, size_t maxlen);限制最大长度的strlenSTM32 推荐防无限读取// 示例安全获取长度 size_t len strnlen(buf, sizeof(buf) - 1);二、比较类函数原型用途STM32 注意点strcmpint strcmp(const char *s1, const char *s2);逐字符比较区分大小写返回 0 表示相等strncmpint strncmp(const char *s1, const char *s2, size_t n);比较前 n 个字符STM32 推荐防溢出strcasecmpint strcasecmp(const char *s1, const char *s2);不区分大小写比较部分库支持Newlib 有// 示例安全比较命令 if (strncmp(cmd, AT, 3) 0) { /* ... */ }三、复制/填充类函数原型用途STM32 注意点strcpychar *strcpy(char *dest, const char *src);复制字符串含\0❌ 危险无边界检查strncpychar *strncpy(char *dest, const char *src, size_t n);复制最多 n 个字符必用但需手动补\0memcpyvoid *memcpy(void *dest, const void *src, size_t n);内存块复制不关心\0STM32 高频使用效率高memsetvoid *memset(void *s, int c, size_t n);内存块设置常用于清空缓冲区// 推荐写法strncpy 强制终止 char buf[32]; strncpy(buf, src, sizeof(buf) - 1); buf[sizeof(buf) - 1] \0; // 确保终止四、连接/拼接类函数原型用途STM32 注意点strcatchar *strcat(char *dest, const char *src);拼接字符串❌ 极易溢出strncatchar *strncat(char *dest, const char *src, size_t n);最多拼接 n 个字符需先确保 dest 有剩余空间snprintfint 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 注意点strchrchar *strchr(const char *s, int c);查找字符首次出现返回 NULL 表示未找到strrchrchar *strrchr(const char *s, int c);查找字符最后一次出现常用于取文件扩展名strstrchar *strstr(const char *haystack, const char *needle);查找子串无则返回 NULLstrpbrkchar *strpbrk(const char *s, const char *accept);查找第一个出现在accept集合的字符常用于分隔符解析// 示例查找 AT 命令返回值中的 \r\n char *p strstr(buf, \r\n);六、转换类函数原型用途STM32 注意点atoiint atoi(const char *nptr);字符串转 int无错误处理不推荐atollong atol(const char *nptr);字符串转 long同上strtollong strtol(const char *nptr, char **endptr, int base);推荐支持进制转换可检测转换错误sprintfint sprintf(char *s, const char *fmt, ...);格式化输出到字符串❌ 无边界检查危险snprintfint snprintf(char *s, size_t n, ...);安全版 sprintfSTM32 必备// 推荐strtol 转换带错误检查 char *end; long val strtol(str, end, 10); if (*end ! \0) { /* 转换不完整 */ }七、实用工具类函数原型用途STM32 场景strtokchar *strtok(char *str, const char *delim);按分隔符切分字符串解析 AT 命令、JSON 字段strspnsize_t strspn(const char *s, const char *accept);返回接受字符集的跨度跳过前导空白/固定头strcspnsize_t strcspn(const char *s, const char *reject);返回排斥字符集的跨度同上memchrvoid *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_rGNU 扩展或自行实现 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 时注意重入性。**