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

memmove处理字符串时第三个参数(strlen/strlen+1)的最佳实践问询

关于memmove第三个参数使用strlen(s)还是strlen(s)+1的疑问解答

好问题!这两种写法看起来结果一致,但背后的可靠性天差地别,咱们一步步拆解:

先看你的测试场景

先把你的代码整理并修正一处拼写错误(sting2→string2):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    char string1[20] = "Hello World";
    char string2[20] = "Hello World";

    printf("\nstring1=\"%s\"\n", string1);
    memmove(string1, string1 + 6, strlen(string1) + 1);
    printf("\nstring1 after memmove \"%s\" using strlen(string1) + 1\n", string1);

    printf("\nstring2=\"%s\"\n", string2);
    memmove(string2, string2 + 6, strlen(string2));
    printf("\nstring2 after memmove \"%s\" using strlen(string2)\n", string2);

    return 0;
}

程序输出:

string1="Hello World"
string1 after memmove "World" using strlen(string1) + 1

string2="Hello World"
string2 after memmove "World" using strlen(string2)

为什么两种写法看起来结果一样?

你的测试里string2是大小为20的字符数组,初始化后"Hello World"只占前11个字节(10个字符+1个\0),剩下的9个字节会被自动初始化为\0。当你用strlen(string2)(值为11)作为memmove的长度时:

  • 从string2+6(指向'W')开始复制的11个字节里,前5个是'W','o','r','l','d',后面6个都是原数组自带的\0
  • 复制到string2开头后,World紧接着就是\0,printf遇到终止符就停止输出,所以看起来和strlen(s)+1的效果一致——但这完全是依赖数组额外空间的巧合。

两种写法的本质区别

  • strlen(s) + 1:这是复制合法C字符串的标准写法。strlen(s)返回的是字符串中有效字符的个数(不包含终止符\0),加1后明确包含了末尾的\0,确保复制后的结果是一个完整、合规的C字符串,无论目标数组的剩余空间多少,都能保证字符串有正确的终止符。
  • strlen(s):这种写法没有复制终止符\0,能正常工作全靠数组额外的\0兜底。如果把string2改成刚好容纳"Hello World"的大小(char string2[11] = "Hello World";),memmove复制11字节后,string2末尾不会有\0,printf会越界读取内存直到遇到\0,这属于未定义行为,可能输出乱码甚至程序崩溃。

最佳实践总结

  • 如果你要复制的是**需要保持C字符串特性(必须以\0结尾)**的内容,一定要用strlen(source_ptr) + 1作为memmove的第三个参数,这是可靠、可移植的写法。
  • 如果你只是复制一段二进制数据(不是C字符串),则根据实际需要复制的字节数来指定长度,此时不需要加1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:43:05