C 库函数 – strlen()(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 C 语言编程中,字符串处理是一个核心且高频的操作场景。而 strlen() 函数作为标准库中用于计算字符串长度的工具,是开发者必须掌握的基础函数之一。无论是验证输入数据的合法性、分配内存空间,还是实现复杂的字符串算法,strlen() 都扮演着不可或缺的角色。对于编程初学者而言,理解其原理与用法能快速提升对指针、内存管理等概念的认知;对于中级开发者,深入分析其底层实现则有助于优化代码性能并避免潜在的陷阱。本文将从基础概念、使用场景、实现原理到进阶技巧,系统性地解析 C 库函数 – strlen() 的核心知识点,并通过代码示例帮助读者建立直观认知。


一、strlen() 的基本概念与功能

1.1 定义与作用

strlen() 是 C 标准库 <string.h> 中提供的一个函数,其功能是计算以 空字符(NULL,即 '\0')结尾的字符串的长度。它的函数原型如下:

size_t strlen(const char *str);  
  • 参数str 是指向字符串的指针,表示需要计算长度的字符串的起始地址。
  • 返回值:返回字符串中有效字符的个数,不包含空终止符。例如,字符串 "Hello" 的长度为 5,而 '\0' 不计入其中。

1.2 字符串的存储特性

在 C 语言中,字符串本质上是 '\0' 结尾的字符数组。例如:

char str[] = "Hello";  

实际存储为:['H', 'e', 'l', 'l', 'o', '\0']。因此,strlen() 的核心逻辑是:从字符串起始地址开始,逐个遍历字符直到遇到 '\0',并统计遍历过的字符数量


二、strlen() 的使用场景与代码示例

2.1 基础用法:计算字符串长度

#include <stdio.h>  
#include <string.h>  

int main() {  
    char greeting[] = "Welcome to C Programming!";  
    size_t length = strlen(greeting);  
    printf("字符串长度为: %zu\n", length); // 输出结果为 22  
    return 0;  
}  

解释

  • 字符串 "Welcome to C Programming!" 包含 22 个有效字符(不含末尾的 '\0')。
  • strlen() 返回的值类型为 size_t,需使用 %zu 格式符进行输出。

2.2 实际应用:输入验证与内存分配

2.2.1 验证用户输入的合法性

#include <stdio.h>  
#include <string.h>  

#define MAX_NAME_LENGTH 50  

void get_user_name(char *name) {  
    fgets(name, MAX_NAME_LENGTH, stdin);  
    // 去除末尾的换行符  
    if (strlen(name) > 0 && name[strlen(name)-1] == '\n') {  
        name[strlen(name)-1] = '\0';  
    }  
}  

int main() {  
    char username[50];  
    get_user_name(username);  
    printf("用户名长度为: %zu\n", strlen(username));  
    return 0;  
}  

作用:通过 strlen() 检查输入的用户名是否过长或包含非法字符,确保程序安全性。

2.2.2 动态内存分配

#include <stdlib.h>  
#include <string.h>  

char *duplicate_string(const char *source) {  
    size_t len = strlen(source);  
    char *copy = (char *)malloc(len + 1); // +1 是为末尾的 '\0' 预留空间  
    if (copy == NULL) {  
        return NULL; // 内存分配失败  
    }  
    strcpy(copy, source);  
    return copy;  
}  

关键点

  • strlen() 确保分配的内存大小恰好满足需求,避免内存浪费或溢出。

三、strlen() 的底层实现原理

3.1 指针与循环遍历

strlen() 的实现可以简化为以下逻辑:

size_t strlen(const char *str) {  
    const char *end = str;  
    while (*end != '\0') {  
        end++; // 指针后移,逐个检查字符  
    }  
    return end - str; // 指针差即为字符串长度  
}  

比喻

  • 可以想象 str 是一座“书架”的起点,end 是一个“移动的指针”。
  • end 遇到书架末尾的“空书”(即 '\0')时停止移动,此时指针移动的步数即为书架的长度。

3.2 性能优化的变种实现

某些标准库(如 GNU 的 glibc)会通过优化指针步长提升效率:

size_t strlen(const char *str) {  
    const char *s = str;  
    while (*s != '\0') {  
        s++; // 逐字节移动  
    }  
    return s - str;  
}  

对比传统实现
| 方法 | 特点 |
|------|------|
| 逐字节遍历 | 简单直接,适合所有场景 |
| 块操作(如 4 字节/次) | 在现代 CPU 中可能更快,但需处理对齐问题 |


四、strlen() 的注意事项与常见陷阱

4.1 非空终止字符串的危险

如果操作的字符串未以 '\0' 结尾(例如通过指针截断或手动构造),strlen() 将会无限循环,直到遇到内存中的随机 '\0'。例如:

char buffer[10];  
strcpy(buffer, "Overflow!"); // 实际写入 11 字节,超过 buffer 容量  
size_t len = strlen(buffer); // 可能导致程序崩溃或不可预测的结果  

解决方案

  • 始终确保字符串以 '\0' 结尾。
  • 使用 strncpy() 等安全函数控制最大写入长度。

4.2 内存越界访问风险

strlen() 的返回值可能超过 size_t 的最大值(如处理超长字符串),但更常见的是未检查输入是否合法。例如:

char *ptr = some_function(); // 可能返回 NULL 或未初始化的指针  
size_t len = strlen(ptr); // 如果 ptr 无效,将导致崩溃  

最佳实践

  • 在调用前验证指针的合法性:if (ptr != NULL)

五、进阶技巧与扩展应用

5.1 结合条件判断实现字符串操作

void truncate_string(char *str, size_t max_len) {  
    if (strlen(str) > max_len) {  
        str[max_len] = '\0'; // 截断字符串并确保以 '\0' 结尾  
    }  
}  

功能:将字符串截断到指定长度,避免数据溢出。

5.2 自定义字符串处理函数

// 计算两个字符串的总长度(不含各自末尾的 '\0')  
size_t total_length(const char *a, const char *b) {  
    return strlen(a) + strlen(b);  
}  

六、与相关函数的对比

6.1 strlen() vs. strnlen()

strnlen() 是 C11 引入的函数,其原型为:

size_t strnlen(const char *str, size_t maxlen);  
  • 区别
    • strnlen() 的第二个参数 maxlen最大遍历次数,避免无限循环风险。
    • 若字符串长度超过 maxlen,则返回 maxlen
  • 适用场景:处理可能未正确终止的字符串时,需优先使用 strnlen()

6.2 strlen() 在多字节字符中的局限性

对于 Unicode 或多字节编码(如 UTF-8),strlen() 的返回值可能与实际字符数不符。例如:

char utf8_str[] = "中文"; // 每个中文字符占用 3 字节  
printf("%zu", strlen(utf8_str)); // 输出 6(字节数),而非字符数 2  

解决方案:使用 mbstowcs() 等多字节处理函数。


结论

C 库函数 – strlen() 是字符串处理的基石,其简洁的接口下隐藏着对内存安全与性能优化的深刻考量。无论是基础的长度计算,还是复杂的安全编程场景,开发者需结合实际需求选择合适的方法,并始终牢记“空字符终止”这一核心原则。通过本文的讲解,希望读者不仅能掌握 strlen() 的用法,更能理解其底层原理与潜在风险,从而在实际开发中编写出健壮、高效的 C 语言代码。

最新发布