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,否则会触发未定义行为。
字节差异对比
- 先明确源数据的有效长度:如果是字符串用
strlen(src),如果是其他内存块则明确其总字节数。 - 对比两者的拷贝字节数:
- 若
num <= strlen(src):strncpy和memcpy的拷贝字节数相同(均为num),但strncpy不会添加'\0',memcpy原样拷贝源数据的num字节。 - 若
num > strlen(src):strncpy拷贝num字节(含填充的'\0'),memcpy仍拷贝num字节(含源数据之后的内存内容)。
- 若
内容的提问来源于stack exchange,提问作者Shelton Liu
相关产品推荐
相关产品推荐

