strncpy 是 C 语言 string.h 头文件里面的定长字符串拷贝函数,它和 strcpy 最大区别就是 strncpy 可以指定拷贝字符个数,属于带长度限制的安全版本拷贝函数,主要作用是把源字符串里面指定数量的字符复制到目标缓冲区,很多初学者最容易踩的坑就是不知道 strncpy 不会自动补零终止符,当源字符串长度大于指定拷贝长度的时候,拷贝完成之后目标缓冲区末尾没有 \0,后续使用 printf 或者其他字符串函数读取的时候就会出现越界乱码,这个函数是 C 语言考研笔试嵌入式开发的高频考点,核心掌握函数原型,拷贝规则,边界情况,还有常见缺陷,写代码的时候一定要理解它并不是完全安全,只是比无限制拷贝的 strcpy 风险低一些。
基础信息对照表
| 项目 | 内容 |
|---|---|
| 头文件 | string.h |
| 函数原型 | char strncpy char dest const char src size_t n |
| 第一个参数 | dest 目标缓冲区首地址 |
| 第二个参数 | src 源字符串首地址 |
| 第三个参数 | n 指定拷贝的字符数量 |
| 返回值 | 返回目标缓冲区 dest 的首地址 |
| 核心特性 | 按指定长度拷贝,不一定自动添加字符串结束符 |
底层执行规则原理
strncpy 执行的时候,会从源字符串 src 依次拷贝字符,一共最多拷贝 n 个字符,这里分两种情况,第一种情况源字符串实际长度小于 n,拷贝完源字符串全部有效字符之后,剩下的位置会自动填充 \0,直到填满 n 个字节。第二种情况源字符串长度大于等于 n,只会拷贝前 n 个字符,不会在末尾追加 \0 终止符,这就是这个函数最关键的设计特点,也是绝大多数 bug 来源,很多人误以为只要用 strncpy 就一定是标准 C 字符串,忽略这个特殊规则,后续调用 strlen strcmp 的时候就会读取缓冲区之外的内存。
同时还要注意,目标缓冲区 dest 的空间必须大于等于 n,否则依然会发生缓冲区溢出,strncpy 只是限制拷贝字符数量,并不会帮你校验目标内存大小,这个误区一定要分清。
实操编码步骤
第一步 引入头文件 string.h,缺少头文件编译器会出现隐式声明警告。
第二步 提前开辟目标数组内存,确认目标缓冲区容量大于等于需要拷贝的 n 值,防止溢出。
第三步 调用 strncpy,传入目标地址,源字符串地址,还有拷贝长度 n。
第四步 重点判断,如果源字符串长度大于等于 n,手动在目标缓冲区第 n 位写入 \0,补齐字符串终止符。
第五步 拷贝完成之后,可以使用 strlen 验证目标字符串,测试正常输出,检查是否存在乱码。
第六步 增加异常判断,源指针 src 或者目标指针 dest 如果是 NULL,要提前做判空,避免空指针崩溃。
strncpy 函数核心就是定长拷贝,对比 strcpy 可以限制拷贝字节数,但是它自带的缺陷就是源串长于 n 的时候不会自动补 \0,实际项目经常需要手动追加结束符,面试经常对比 strncpy strcpy strlcpy,考点就是这个不自动补零的特性,编码的时候不能盲目认为 strncpy 就是绝对安全函数。
【常见问题】
问题 1 strncpy 函数用法里面为什么经常出现乱码
回答 1 strncpy 函数用法里面出现乱码,绝大多数原因是源字符串长度大于拷贝长度 n,strncpy 没有自动添加 \0 终止符,后续字符串函数识别不到结束标记。
问题 2 strncpy 函数用法和 strcpy 有什么核心区别
回答 1 strncpy 函数用法支持指定拷贝字符数量,strcpy 是一直拷贝直到源字符串遇到 \0,没有长度上限,strcpy 更容易缓冲区溢出。
问题 3 strncpy 函数用法目标缓冲区空间不够会怎么样
回答 1 strncpy 函数用法如果目标缓冲区容量小于 n,依然会发生缓冲区溢出,strncpy 本身不会校验目标内存大小,这个是很多新手的误区。
问题 4 strncpy 函数用法什么时候会自动填充 \0
回答 1 strncpy 函数用法,当源字符串实际长度小于 n 的时候,拷贝完源串全部字符之后,剩余位置会自动填充 \0 直到填满 n 个字节。
【免责申明】
本内容为 C 语言标准库函数学习讲解,不同编译器对 strncpy 实现细节基本遵循 C 标准,代码示例仅供学习参考,正式项目开发请结合 C 标准文档和编译器官方说明,生产环境可评估更安全的替代拷贝函数。


