当前位置: 首页 > news >正文

strlen 函数的使用与模拟实现

目录

一、strlen 函数的基本特性

二、使用注意事项

补码是计算机表示有符号整数的标准方式,其核心规则是:(后面会讲解)

具体执行过程

为什么会出现这种情况

补码计算详细解释

三、strlen 的模拟实现

方法1:计数器方式

方法2:递归方式(不创建临时变量)

方法3:指针相减方式

四、实际应用建议


一、strlen 函数的基本特性

strlen 是 C 语言标准库中用于计算字符串长度的函数,其原型如下:

size_t strlen(const char *str);

该函数具有以下特点:

  1. 以 '\0' 为结束标志:字符串必须以空字符 '\0' 结尾,函数返回的是 '\0' 前面出现的字符个数(不包含 '\0' 本身)

  2. 返回值类型:返回值为 size_t 类型,这是一个无符号整型(unsigned integer),这在比较字符串长度时容易导致错误

  3. 头文件:使用前需要包含 <string.h> 头文件


二、使用注意事项

        在这个例子中,关键问题在于 strlen() 返回的是 size_t 类型(无符号整数),而两个无符号整数相减的结果也是无符号整数,这会导致一些违反直觉的比较结果。

#include <stdio.h>
#include <string.h>int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if(strlen(str2) - strlen(str1) > 0){printf("str2 > str1\n");  // 这个分支会被执行}else{printf("str1 > str2\n");}return 0;
}

        上述代码会输出 "str2 > str1",尽管直观上 "abcdef" 比 "bbb" 长。这是因为无符号数相减的结果也是无符号数,永远不会小于0。

补码是计算机表示有符号整数的标准方式,其核心规则是:(后面会讲解)

  • 正数的补码 = 其二进制原码(和原码相同)

  • 负数的补码 = 其绝对值的二进制表示取反(按位取反)后加 1

具体执行过程

  1. strlen(str2) 返回 3(size_t 类型)

  2. strlen(str1) 返回 6(size_t 类型)

  3. 计算 3 - 6

    • 对于无符号整数,这个操作不会产生负数

    • 在32位系统中,size_t 通常是32位无符号整数

    • 3 - 6 的补码计算:

      • 3 的二进制: 0000 0000 0000 0000 0000 0000 0000 0011

      • -6 的二进制(补码): 1111 1111 1111 1111 1111 1111 1111 1010

      • 相加结果: 1111 1111 1111 1111 1111 1111 1111 1101

    • 这个结果解释为无符号整数是一个很大的正数(4294967293)

  4. 比较 (4294967293 > 0) 结果为真

为什么会出现这种情况

  • 无符号整数没有负数的概念,当减法结果为"负"时,会回绕到最大的无符号整数

  • 这是C语言中常见的安全隐患,称为"无符号整数回绕"(unsigned integer wrap-around)

补码计算详细解释

在计算机中,负数用补码表示,减法实际上是加负数的补码:

  1. 计算 -6 的补码:

    • 6 的二进制: 0000 0000 0000 0000 0000 0000 0000 0110

    • 取反: 1111 1111 1111 1111 1111 1111 1111 1001

    • 加1: 1111 1111 1111 1111 1111 1111 1111 1010 (这就是-6的补码)

  2. 计算 3 + (-6):

      0000 0000 0000 0000 0000 0000 0000 0011 (3)
    + 1111 1111 1111 1111 1111 1111 1111 1010 (-6)
    -----------------------------------------1111 1111 1111 1111 1111 1111 1111 1101 (结果)
  3. 如果解释为有符号整数,这是-3

  4. 但作为无符号整数,这是4294967293


三、strlen 的模拟实现

方法1:计数器方式

#include <assert.h>
#include <stdio.h>int my_strlen(const char* str)
{int count = 0;assert(str != NULL);  // 确保指针非空while (*str != '\0'){count++;str++;}return count;
}int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";printf("%zu\n", my_strlen(str1));printf("%zu\n", my_strlen(str2));return 0;
}

方法2:递归方式(不创建临时变量)

#include <assert.h>
#include <stdio.h>int my_strlen(const char* str)
{assert(str != NULL);if (*str == '\0')return 0;elsereturn 1 + my_strlen(str + 1);
}int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";printf("%zu\n", my_strlen(str1));printf("%zu\n", my_strlen(str2));return 0;
}

先拆分(递推),再回归(返回):(忘记了的话可以先回顾递归那一章节的知识点)

方法3:指针相减方式

#include <assert.h>
#include <stdio.h>int my_strlen(const char* str)
{assert(str != NULL);const char* p = str;  // 使用const保持一致性while (*p != '\0')p++;return p - str;  // 指针相减得到元素个数
}int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";printf("%zu\n", my_strlen(str1));printf("%zu\n", my_strlen(str2));return 0;
}


四、实际应用建议

  1. 安全性:在实际项目中,应考虑添加参数检查(如使用assert)

  2. const修饰:使用const修饰指针参数可以防止意外修改字符串内容

  3. 性能考虑:指针相减的方式通常效率最高,递归方式最不推荐在实际项目中使用

  4. 边界情况:处理空字符串("")时应返回0,处理NULL指针时应进行错误处理

        这些实现方式展示了C语言中字符串操作的多种思路,理解它们有助于深入掌握指针和字符串处理的核心概念。

http://www.lryc.cn/news/625922.html

相关文章:

  • 云原生俱乐部-mysql知识点归纳(2)
  • Java网络编程:TCP与UDP通信实现及网络编程基础
  • 无人机场景 - 目标检测数据集 - 山林野火烟雾检测数据集下载「包含VOC、COCO、YOLO三种格式」
  • FastAPI 请求详解:全面掌握各种请求类型处理
  • 《基于大数据的全球用水量数据可视化分析系统》用Python+Django开发,为什么导师却推荐用Java+Spring Boot?真相揭秘……
  • 实践项目-1
  • Matplotlib数据可视化实战:Matplotlib图表注释与美化入门
  • LeetCode100-560和为K的子数组
  • Rust学习笔记(七)|错误处理
  • 2025年渗透测试面试题总结-21(题目+回答)
  • 堆、方法区、虚拟机栈、本地方法栈、程序计数器
  • RabbitMQ:SpringAMQP 多消费者绑定同一队列
  • Java配置文件
  • 第1章 React组件开发基础
  • 第10章 React应用测试
  • 我的SSM框架自学2
  • IDEA测试代码报java file outset source root异常
  • STM32-FreeRTOS快速入门指南(中)
  • 【软件安装】VScode介绍安装步骤及中文界面设置方法
  • 从数据孤岛到实时互联:Canal 驱动的系统间数据同步实战指南
  • Java 11中的Collections类详解
  • 正式签约 | OpenLoong 项目正式捐赠至开放原子开源基金会,成为全国首个具身智能方向孵化项目!
  • Vulkan笔记(十三)-帧缓冲区与命令池命令缓冲区
  • 使用 SemanticKernel 连接本地大模型 Ollama
  • 11.Ansible自动化之-内容集管理
  • 快手Klear-Reasoner登顶8B模型榜首,GPPO算法双效强化稳定性与探索能力!
  • 图像增强——灰度变换增强(线性,对数,指数)、空间滤波增强、频域增强、主成分/彩色合成增强(原理解释和代码示例)
  • FPGA 在情绪识别领域的护理应用(一)
  • Spring Boot应用实现图片资源服务
  • 电商数据分析可视化预测系统