45

我希望从一个特定的起点将特定长度的内容从一个缓冲区复制到另一个缓冲区。我检查了memcpy(),但是当我也想指定起始索引时,它只需要复制内容的长度。

是否有任何功能可以做到这一点,或者有什么好的方法可以用现有的memcpy功能做到这一点?

4

9 回答 9

92

我总是喜欢语法

memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) );
于 2009-07-22T08:52:12.213 回答
31

只需将您想要的偏移量添加到缓冲区的地址即可。

char abuff[100], bbuff[100];
....
memcpy( bbuff, abuff + 5, 10 );

这将从 abuff[5] 开始的 10 个字节复制到 bbuff。

于 2009-07-22T07:32:25.900 回答
14

只需将偏移量添加到地址即可。例如,如果您想从第 N 个字节开始复制缓冲区:

memcpy( destination, source + N, sourceLen - N );

这将复制到destination. 如果您还想偏移目的地 - 将偏移量添加到两者:

memcpy( destination + N, source + N, sourceLen - N );
于 2009-07-22T07:32:09.660 回答
4

不需要索引,因为您可以简单地按指定的字节数更新源指针。以下包装器应该可以解决问题

void* memcpy_index(void *s1, const void *s2, size_t index, size_t n) {
  s2 = ((char*)s2)+index;
  return memcpy(s1, s2,n);
}
于 2009-07-22T07:33:27.253 回答
2

只需增加指向起始索引的指针即可。

例子

const unsigned char * src = reinterpret_cast<const unsigned char*>(your source);
unsigned char * dest = reinterpret_cast<unsigned char *>(your dest);
memcpy(dest, src + offset, len);

那么使用 STL 集合来避免内存访问错误呢?

于 2009-07-22T07:33:28.657 回答
1

除了匿名回答之外,该站点还需要一种允许匿名跟进的方法。

为什么我不止一次看到“索引”必须以 1 字节为单位的这种疯狂断言?这与惯例完全相反。“索引”通常是象征性的,它的物理字节偏移量由数组(或向量,它甚至可能没有数组的物理布局)中元素的大小决定,但 memcpy() 也与课程)。

因此,数组中的第 5 个元素的“索引”为 5,但是:

  • 如果数组是 char 类型,则该“索引”的字节偏移量为 5。
  • 如果数组是 short 类型(在 x86 上),则该“索引”的字节偏移量为 10。
  • 如果数组是 int 类型(在 x86 上),则该“索引”的字节偏移量为 20。
  • 如果数组是某个大型 48 字节对象的类型,则该“索引”的字节偏移量为 240。

哪种方式是访问该特定元素的正确方式是一个侧面。重要的部分是您了解差异,选择一个,并使代码正确。


关于单词的含义,我宁愿阅读:

 void* memcpy_offset(void *s1, const void *s2, size_t offset, size_t n);

比:

 void* memcpy_index(void *s1, const void *s2, size_t index, size_t n);

我发现完全通用的 void * 可能具有“索引”的想法具有误导性。(当我们在这里时,“dest”和“source”或“in”和“out”将比“s1”和“s2”更清晰。当您选择不言自明时,代码不需要那么多注释变量名。)

于 2010-02-05T04:26:07.147 回答
0

只需将索引添加到缓冲区的地址,并将其memcpy()作为源参数传递给,例如从缓冲区 b 的第 3 项复制

char a[10], b[20];
::memcpy(a,b+2,10);

还要考虑缓冲区中项目的类型,memcpy() 的长度(第 3 个)参数以字节为单位,因此要复制 4 个整数,您应放置 4*sizeof(int) - 这可能是 16(在 32 位系统。但类型与起始地址无关,因为指针算法:

int a[10], b[10];
::memcpy( a+2, b, 2*sizeof(int) );
// a+2 will be address of 3rd item in buffer a
// not address of 1st item + 2 bytes
于 2009-07-22T08:18:47.647 回答
0

你可以有一个像下面这样的功能。

template<typename T>
T* memcopy_index(T* dst,T* src,unsigned int index, unsigned int element_count)
{
    return (T*)memcpy(dst,src + index, element_count * sizeof(T));
}

它可以如下使用:

int src[]={0,1,2,3,4,5,6};
int dst[15];

memcopy_index(dst,src,2,5);    //copy 5 elements from index 2

您必须确保目标缓冲区有足够的空间来复制元素。

于 2009-07-22T09:05:48.237 回答
0

如果您使用的是 c++,最好使用 std::copy() 而不是 memcpy()。std::copy 可以像迭代器一样轻松地获取指针。

例如

int src[20];
int dst[15];

// Copy last 10 elements of src[] to first 10 elements of dst[]
std::copy( src+10, src+20, dst );

与 memcpy() 一样,您有责任确保指针有效。

笔记。如果您的使用对性能至关重要,您可能会更快地找到其他答案中详述的 memcpy(),但可能不会太多。

于 2009-07-22T17:04:08.223 回答