不能直接用 strlen 是因为嵌入式、裸机或安全场景下标准库被禁用或不可信,需手写安全可靠的字符串长度计算逻辑,核心是空指针检查、终止符判断及类型一致性。

为什么不能直接用 strlen?
有些嵌入式环境、裸机开发或安全审计场景下,标准库被禁用或不可信,必须手写字符串长度计算逻辑。关键不是“怎么算”,而是“怎么算得准且不越界”——strlen 的行为定义很明确:从首地址开始计数,直到遇到第一个 '\0',不包含该终止符。
最简可行的手动实现(C 风格)
核心就是指针遍历 + 终止判断,但要注意两点:空指针检查、字符类型一致性。下面这个版本能通过绝大多数基础测试:
size_t my_strlen(const char* s) {
if (!s) return 0;
const char* p = s;
while (*p != '\0') ++p;
return p - s;
}常见错误现象:my_strlen(NULL) 导致段错误;用 int 当返回类型导致大字符串截断(如 >2GB 字符串在 64 位系统上);循环里写成 *p++ 却忘了先判空。
C++ 中更安全的重载与模板写法
如果项目允许 C++ 特性,可以用引用避免空指针问题,或用模板适配不同字符类型:
立即学习“C++免费学习笔记(深入)”;
-
size_t my_strlen(const char* s):保留 C 兼容接口,仍需手动判空 -
size_t my_strlen(const char (&)[N]):对字面量数组可编译期求长,但无法用于运行时分配的字符串 - 若要支持
std::string_view,直接用.size(),别重复造轮子
性能影响:纯指针遍历无额外开销,比某些带分支预测优化的 libc 实现略慢,但差异在纳秒级,不用纠结。
容易被忽略的边界细节
实际调试中最常栽跟头的地方不是算法,而是调用上下文:
- 传入非 null-terminated 字符串(比如从二进制数据里截一段当字符串用),结果完全不可预测
- 字符串含中间
'\0'(如处理某些协议包),my_strlen只会返回到第一个'\0'的位置,这不是 bug,是符合定义的行为 - 用
char16_t*或宽字符时,绝对不能套用这个函数——sizeof(char16_t) != sizeof(char),且终止符是u'\0'
真正难的从来不是写几行循环,而是确认你传进去的到底是不是一个以 '\0' 结尾的 char 序列。


















