C++ 常用字符串函数详解:cstring.h 核心 API 与注意事项

Dylan
Dylan
发布时间:2026-10-16| 6人浏览过
原创

C++ 中的 cstring(兼容 C 语言 string.h)提供了大量处理字符数组的标准函数。掌握这些函数是进行底层数据处理的基础,但也伴随着较高的安全隐患。本文梳理了最常用的字符串长度、拼接、复制和比较函数,特别是针对 strcpy 等函数的缓冲区溢出风险给出具体解决方案,并深度解析了 memset 在不同类型数组初始化中的特殊表现。

准备工作与头文件引入

cstring 库是 C 语言遗留的标准库在 C++ 中的存在形式,主要用于操作原生字符数组(char*)。在使用前需包含对应头文件:

#include <cstring>
#include <iostream>
using namespace std;

strlen:获取真实字符串长度

由于 C++ 编译器依赖终止符 \0 来识别字符串结束位置,因此字符数组的实际容量往往大于其内部存储的有效字符串长度。strlen 函数能精准返回不包含 \0 的字符个数。

char name[100] = "hello world";
cout << strlen(name) << endl; // 输出: 11

即使分配了 char name[100],只要内容是 "hello world",其长度依然只计算为 11。

字符串拼接函数:strcat 与 strncat

第 1 步:理解 strcat 拼接机制

strcat(char *dest, const char *src) 会将 src 追加到 dest 的末尾,并返回 dest 指针。原 dest 末尾的 \0 会被 src 的第一个字符覆盖。

char name[100] = "hello world";
char level[100] = " concat test";

// dest必须预留足够空间容纳拼接后的新字符串
char *ret = strcat(name, level); 
cout << ret << endl; // 输出: hello world concat test

第 2 步:使用 strncat 限制拷贝长度

为防止越界或仅需部分拼接,推荐使用 strncat。第三个参数 n 指定从 src 最多拷贝的字符数(不含自动添加的 \0)。

char name[100] = "hello world";
char level[100] = "concat test";

// 仅拼接 level 的前4个字符
char *ret = strncat(name, level, 4);
cout << name << endl; // 输出: hello worldconc

字符串复制函数:strcpy 的安全陷阱

第 3 步:警惕缓冲区溢出

strcpy(char *dest, const char *src) 将 src 完整复制到 dest。此函数不会检查目标空间是否足够,极易引发运行时崩溃或内存损坏。

char name[10] = "";
char level[100] = "concat test";

// 编译通过,但运行时会发生栈溢出错误
strcpy(name, level); 


上图展示了典型的内存访问违规报错。在实际开发中,务必确保 dest 有足够空间,或者直接使用更安全的方式(如 std::string 或手动截断)。

第 4 步:覆盖行为

如果 dest 原有内容被完全覆盖,原数据将丢失:

char name[15] = "abc";
strcpy(name, "concat test"); 
cout << name << endl; // abc 被清空,输出 concat test

第 5 步:使用 strncpy 增加安全性

strncpy 增加了长度控制参数 n。它最多拷贝 n 个字符;若 src 不足 n 位,剩余部分填充 \0。

char name[15] = "abc";
char level[100] = "concat test";

strncpy(name, level, 4);
cout << name << endl; // 输出: conc (注意后续可能有随机乱码,取决于未处理的内存)

提示:strncpy 并不保证结果一定以 \0 结尾(除非 src 长度小于 n),使用时需小心。

批量填充函数:memset 的深度解析

第 6 步:理解 memset 字节级操作

memset(void *str, int c, size_t n) 逐字节地设置内存。常用于清零数组或填充特定字符。

char name[15] = "abc";
memset(name, 'c', 10);
cout << name << endl; // 前10个字节变为'c'

第 7 步:整型数组初始化的误区

当对 int 数组调用 memset 时,因为一个 int 占 4 个字节,传入的值会被重复填充 4 次。例如 memset(a, 1, sizeof a) 会将每个字节填为 0x01,最终整数变为 0x01010101(十进制约 1680 万),而非 1。

对于整型数组,memset 仅推荐用于以下三种情况:

// 1. 置零 (最常用)
memset(a, 0, sizeof a);

// 2. 全 -1 (二进制补码全1)
memset(a, -1, sizeof a);

// 3. 大数值初始化 (如贪心算法初始化距离)
memset(a, 0x3f, sizeof a); // 0x3f3f3f3f ≈ 1e9

字符串比较函数:strcmp 与 strncmp

第 8 步:字典序比较

strcmp(const char *s1, const char *s2) 从左向右逐个对比 ASCII 值:

  • 返回值 < 0:s1 小于 s2
  • 返回值 = 0:两字符串相等
  • 返回值 > 0:s1 大于 s2
cout << strcmp("abc", "abcd") << endl; // 输出负数 (如-100),说明 abc 排在 abcd 前面

第 9 步:限定长度的比较

同前文逻辑,strncmp 可额外指定最大比较字符数,适用于协议头部分析或部分匹配场景。

查找子串:strstr

strstr(char *haystack, char *needle) 在 haystack 中查找 needle 第一次出现的位置,并返回该位置的指针。若未找到则返回 NULL。

char name[15] = "search-test";
char *ret = strstr(name, "-");
cout << ret << endl; // 输出: -test (直接打印从此位置开始的后缀)


简要总结

以上关于 C++ cstring.h 常用函数的详细内容,更多关于 C++ 标准库操作与内存安全的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。