函数原型

errno_t memcpy_s(void *dest, size_t destSize, const void *src, size_t count);

函数描述

memcpy_s 函数,从 src 中复制 count 个字节到 dest 中。它是 memcpy 的安全版本,因为参数中限制了目标内存区域的大小。

是在内存级别上直接进行拷贝操作,但注意它一次拷贝的数量为一个字节,而不是一个位(比特)。

参数描述

  1. dest:目标数组,或者说目标内存区域
  2. destSize:目标内存区域的大小,其单位是字节
  3. src:源数组,或者说源内存区域
  4. count:要复制的源内存区域元素的个数,其单位是字节

返回值

如果成功则返回零(来自 MSDN)

这里有一个坑,那就是关于 destSize 和 count 的值,它们都是指的字节数(最开始我以为是元素个数)。

举一个例子,比如我有如下数组:

	long src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	long dest[10] = { 0 };

现在我将 src 中的元素通过 memcpy_s 函数赋值到 dest 中,最开始我以为 destSize 和 count 表示的是元素个数,于是填写的都是 10,如下。

void Malloc_m_memcopy()
{
	long src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	long dest[10] = { 0 };

	memcpy_s(dest, 10, src, 10); 

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", dest[i]); // 1 2 3 0 0 0 0 0 0 0
	}
}

显然,printf 打印的数据不正常。因为实际上,destSize 和 count 都是以字节数为单位,而非个数。

所以我们看上面,long 在我的环境中(windows10 64位,vs2015 下)其大小为 4 个字节。所以实际填写的值应该是 destSize 和 count 都为 10 * 4(即 10 个元素,每个元素占用 4 个字节)。

下面是正确的代码:

void Malloc_m_memcopy()
{
	long src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	long dest[10] = { 0 };

	memcpy_s(dest, 10 * 4, src, 10 * 4);

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", dest[i]); // 1 2 3 4 5 6 7 8 9 10
	}
}

可以看到正常输出了。

或者你也可以用 sizeof 函数来计算 src 和 dest 占用的元素的字节数,sizeof 用来计算对象或类型在当前系统下占用内存的字节数
【注】sizeof 返回的是变量在当前编译器下的字节数

void Malloc_m_memcopy()
{
	long src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	long *dest = (long *)malloc(sizeof(long) * 10 );

	memcpy_s(dest, sizeof(long) * 10, src, sizeof(src));

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", dest[i]); // 1 2 3 4 5 6 7 8 9 10
	}
}

参考

  1. memcpy_s:msdn
  2. memcpy_s:cppreference
  3. memcpy_s in C:比参考 1,2 总结的好
  4. What is size_t in C?:StackOverflow
  5. size_t data type in C
  6. Why is rsize_t defined?:StackOverflow

拓展

  1. Copying overlapping memory:memcpy 存在的内存重叠问题
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐