You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

memcpy与strncpy用法对比:行为差异及内存拷贝字节判断咨询

memcpy与strncpy的行为差异及内存拷贝字节分析

函数原型

strncpy

char * strncpy ( char * destination, const char * source, size_t num );

memcpy

void * memcpy ( void * destination, const void * source, size_t num );

测试代码与输出

测试代码

char src[] = "Hello World";
char dst[20];

strncpy(dst, src, 5);
printf("%zu-", strlen(dst));

memcpy(dst, src, sizeof(dst));
printf("%zu-", strlen(dst));

strncpy(dst, src, 5);
printf("%zu", strlen(dst));

实际输出

5-11-11

行为差异解析

第一次调用strncpy(输出5)

  • strncpy从src拷贝前5个字符到dst,由于指定的拷贝长度5小于src的有效字符长度(11),不会自动在dst末尾添加字符串结束符'\0'。
  • 此时dst前5位为"Hello",后续内存是未初始化的栈随机值,恰好第一个'\0'出现在第5个字符之后,因此strlen(dst)返回5。

第二次调用memcpy(输出11)

  • memcpy是通用内存拷贝函数,严格按照指定字节数(sizeof(dst)=20)拷贝内存内容,不关心字符串结束符。
  • src的完整内容是"Hello World\0"(共12字节),memcpy会把这12字节完整拷贝到dst,剩余8字节拷贝的是src数组后的栈内存数据。
  • 由于dst第12位保留了src的'\0',strlen(dst)统计到'\0'前的11个有效字符,返回11。

第三次调用strncpy(输出11)

  • strncpy再次拷贝src的前5个字符到dst,仅覆盖dst的前5位,不会修改后续内存内容。
  • 此时dst前5位为"Hello",第6到11位仍为" World",第12位的'\0'也保留,因此strlen(dst)依然统计到11个有效字符。

核心行为差异总结

  • 字符串结束符处理:
    • strncpy:若拷贝长度num小于源字符串长度,不会自动添加'\0';若num大于源字符串长度,会用'\0'填充到num字节。
    • memcpy:不处理'\0',仅严格拷贝指定字节数的内存,不管源数据是否为字符串。
  • 适用场景:
    • strncpy专为字符串设计,用于处理以'\0'结尾的字符串拷贝。
    • memcpy是通用内存拷贝工具,可用于任意类型的内存块(如结构体、数组)拷贝。

内存拷贝字节数的确定方法

strncpy的拷贝字节数

  • 当num <= strlen(src):实际拷贝num字节(仅源字符串的前num个字符,无'\0'填充)。
  • 当num > strlen(src):实际拷贝num字节(源字符串的所有字符 + num - strlen(src)个'\0')。

memcpy的拷贝字节数

  • 严格等于指定的num参数,与源数据内容无关。使用时需确保源内存的有效长度至少为num,否则会触发未定义行为。

字节差异对比

  1. 先明确源数据的有效长度:如果是字符串用strlen(src),如果是其他内存块则明确其总字节数。
  2. 对比两者的拷贝字节数:
    • 若num <= strlen(src):strncpy和memcpy的拷贝字节数相同(均为num),但strncpy不会添加'\0',memcpy原样拷贝源数据的num字节。
    • 若num > strlen(src):strncpy拷贝num字节(含填充的'\0'),memcpy仍拷贝num字节(含源数据之后的内存内容)。

内容的提问来源于stack exchange,提问作者Shelton Liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 02:20:11