strlen 对非 '\0' 结尾的字符数组会出错,因为它从指针起始地址向后扫描直至遇到第一个 '\0',若数组无 '\0' 结尾则越界读取,导致结果未定义;正确做法是确保字符串以 '\0' 结尾或改用已知长度操作。

strlen 为什么对非 null 结尾的字符数组会出错
strlen 不是“求字符数组长度”,而是从指针地址开始向后扫描,直到遇到第一个 '\0' 字符为止。它不关心你声明的数组有多大,只认内存里有没有 '\0'。如果字符数组没以 '\0' 结尾(比如用 {'h','e','l','l','o'} 初始化,或手动赋值但漏写结尾),strlen 就会越界读取,结果不可预测——可能返回随机大数、崩溃,或恰好“碰巧”停在某个内存里的 '\0' 上。
怎么确保 strlen 能正确工作
关键不是调用 strlen,而是让数据本身符合 C 风格字符串要求:以 '\0' 结尾。常见做法有:
- 用字符串字面量初始化:
char s[] = "hello";—— 编译器自动补'\0',strlen(s)返回 5 - 显式留出空间并手动置零:
char s[6] = {'h','e','l','l','o'};—— 数组长度为 6,未初始化的s[5]默认为 0 - 用
memset清零再填充:char s[10]; memset(s, 0, sizeof(s)); memcpy(s, "hi", 2);,之后strlen(s)才安全 - 避免这种写法:
char s[5] = {'h','e','l','l','o'};—— 没空间放'\0',strlen必然越界
替代方案:当无法保证 '\0' 结尾时怎么办
如果你手头只有纯字符数组(比如从二进制协议里读出的一段数据)、明确知道长度,但不确定是否含 '\0',就别用 strlen。直接用已知长度,或用 std::string_view(C++17)封装:
char data[] = {'a', 'b', 'c', 0, 'd'}; // 中间有 '\0',但不是结尾
std::string_view sv(data, sizeof(data)); // 长度明确传入,不依赖 '\0'
// sv.length() == 5,安全可靠
或者用 std::count 手动找第一个 '<p>或者用 <code>std::count 手动找第一个 '\0'(但效率低,仅调试用):auto pos = std::find(std::begin(data), std::end(data), '\0');
auto pos = std::find(std::begin(data), std::end(data), '<p>或者用 <code>std::count 手动找第一个 '\0'(但效率低,仅调试用):auto pos = std::find(std::begin(data), std::end(data), '\0');');立即学习“C++免费学习笔记(深入)”;
strlen 的返回值类型容易被忽略
strlen 返回的是 size_t,不是 int。在 64 位系统上它是无符号长整型。直接和负数比较、或赋给 int 变量可能触发隐式转换警告甚至逻辑错误:
- 错:
if (strlen(s) —— <code>-1被转成极大正数,条件恒假 - 错:
int len = strlen(s);—— 若字符串超 2GB(罕见但可能),截断溢出 - 对:
size_t len = strlen(s);,或用auto len = strlen(s);
真正麻烦的从来不是怎么调 strlen,而是忘了它根本不看数组声明,只信内存里那个看不见又必须存在的 '\0'。


















