strcpy、memcpy区别

strcpy和memcpy主要有以下3方面的区别。
  1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。企业中使用memcpy很平常,因为需要拷贝大量的结构体参数。memcpy通常与memset函数配合使用。
  2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。因此strcpy会默认复制字符串的结束符“\0”,而memcpy,当3个参数决定复制的长度包括了\0字符时,则也会复制\0,不包括\0字符的长度,则不会复制\0。
  3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

strcpy、strncpy的区别

strcpy()是依据源串的/0作为结束判断的,不检查目标空间Buffer的Size,如果目标空间不够,就有BufferOverflow问题。
strncpy(char* dst,char * src, size_t count),从源地址src拷贝count字符到目的地址dst,虽有count做限制,当strlen(src)>strlen(dst)时,还是会存在目标空间地址越界,所以使用strncpy的正确方法应该是,首先对dst空间用memset清零, strncpy(char dst,char * src, sizeof(dst)-1)。*

strncpy和memcpy的区别

如果只是操作字符串,其实这两个函数差别不大,类型转换都不是问题。
有一点差别就是当你要拷贝大于原字符串长度的时候,也就是 n 大于源字符串长度,strncpy 会用 ‘\0’ 来填充,而 memcpy 只完全复制源地址空间的字符,包括末尾的一个\0,再多余的字符不会出现用多个\0来填充,而是保持目的地址的已有的内存值,所以超过src长度的内存区域在目的地址内存中是不确定的。
嵌入式编程需要注意,比如串口里不传输字符串,而是传输十六进制比特流[^1]。
因为16进制流里难免出现0x00,如果用 strncpy 来拷贝数据,在出现0x00的地方就认为是字符串结束了,然后剩余的长度都会用0x00(‘\0’) 填充。而memcpy就不会出现这个问题。

数据流: a1 a2 a3 a4 a5 a6 a7 a8 a9 00 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9
用strncpy之后:a1 a2 a3 a4 a5 a6 a7 a8 a9 00 00 00 00 00 00 00 00 00 00 00
用memcpy之后:a1 a2 a3 a4 a5 a6 a7 a8 a9 00 b0 b1 b2 b3 b4 b5 b6 b7 b8 b

代码

/*********************************************************
参考:
https://blog.csdn.net/zhanghuan_wangkai/article/details/51674935

*  *******************************************************/
#include <stdio.h>
#include<string.h>
#include <assert.h>

void *my_memcpy(void *memTo, const void *memFrom, int size)
{
	//入口参数检查
	assert((memTo != NULL) && (memFrom != NULL));
	char *tempFrom = (char *)memFrom;
	char *tempto = (char *)memTo;

	//循环size次,复制memFrom的值到memTo中
	while (size-- > 0)
	{
		*tempto++ = *tempFrom++;
	}
	return memTo;
}


int main()
{
	char *strSrc = "hello wrold";
	char strDest[7] = {0};
	

	//strpcy-------------------------
	strcpy(strDest, strSrc);
	printf("strDest:%s\n", strDest);//strDest:hello wrold\0,会拷贝strSrc的末尾\0,当strlen(strSrc)>sizeof(strDest),strDest越界

	char s1[] = "12345";
	char s2[] = "678";
	strcpy(s1, s2);
	printf("s1:%s\n", s1);//s1内存:678\05\0,会拷贝strSrc的末尾\0


	//栈内存是一个自顶向下分布的数据结构,那么越先定义的变量地址就越高,越后定义的地址就越低。 \
	s比d定义在前, 那么s得到了高地址, 而d得到了相对低的地址
	char s[] = "abcdefghi";
	char d[] = "abc";//末尾\0
	strcpy(d, s);
	printf("d=%s,\ns=%s", d, s);//s中内存:efghi0ghi0,输出efghi
	/*
	低------->高地址,低地址先存储d数组,共4个字符,包括\0,
	abc0abcdefghi0
	strcpy拷贝后,d数组越界,破坏了s数组里的数据
	abcdefghi0ghi0
	*/


	//strnpcy------------------------------
	//如果strlen(src)的值小于len,dst数组就用\
	额外的\0字节填充到len长度,如果strlen(src)的值大于或等于len,那么只有len个字符被复制到dst中。

	char message[] = "abcd";
	strncpy(message, "abcde", 5);
	printf("message:%s\n", message);//strlen(src)>strlen(dst),message内存值:abcde??乱码

	char message0[] = "abcd";
	strncpy(message0, "abcde", 7);
	printf("message0:%s\n", message0);//后面会填充2个0,凑成7个字符,message内存值:abcde00


	char message1[] = "abcdefghik";
	strncpy(message1, "abe", 5);
	printf("message1:%s\n", message1);//message1内存值,abe后自动填充2个0,凑成5个字符:abe00fghik0----strlen(src)的值小于len

	char message3[] = "abcdefghik";
	strncpy(message3, "abe", 4);
	printf("message3:%s\n", message3);//message3内存值,abe后自动填充1个0,凑成4个字符:abe0efghik0----strlen(src)的值小于len

	char message2[] = "abcdefghik";
	strncpy(message2, "abe", 3);
	printf("message2:%s\n", message2);//message2内存值,刚好拷贝abe3个字符:abedefghik0----strlen(src)的值等于len

	char message4[] = "abcdefghik";
	strncpy(message4, "mnq", 2);
	printf("message4:%s\n", message4);//message4内存值,只拷贝前2个字符:mncdefghik0----strlen(src)的值大于len


	//memcpy,src和dest所指内存区域不能重叠--------
	char message6[] = "abcdefghik";
	memcpy(message6, "mnq", 2);
	printf("message6:%s\n", message6);//message6内存值,只拷贝前2个字符:mncdefghik0,与strncpy一样----strlen(src)的值大于len

	char message8[] = "abcdefghik";
	memcpy(message8, "mn", 2);
	printf("message8:%s\n", message8);//message8内存值,只拷贝前2个字符:mncdefghik0,与strncpy一样----strlen(src)的值等于len

	char message7[] = "abcdefghik";
	memcpy(message7, "abe", 5);
	printf("message7:%s\n", message7);//message7内存值,只拷贝sizeof("abe")共4个字符:abe0defghik0,内存中第5个(多余)\
									  字符是未知的,而strncpy是默认用\0填充-----strlen(src)的值小于len

	return 0;
}

运行结果

在这里插入图片描述

参考

1.https://blog.csdn.net/gu332523602/article/details/78428819

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐