关于带有startIndex的c ++:memcpy?

memcpy with startIndex?

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

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


我总是喜欢语法

1
memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) );


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

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

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


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

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

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

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


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

1
2
3
4
void* memcpy_index(void *s1, const void *s2, size_t index, size_t n) {
  s2 = ((char*)s2)+index;
  return memcpy(s1, s2,n);
}


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

1
2
3
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集合避免内存访问错误?


除了匿名答案之外,该网站还需要一种允许匿名后续活动的方法。

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

因此,数组中的第5个元素具有"索引" 5,但是:

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

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

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

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

比:

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

我发现这样一个想法,即一个完全通用的void *可能会有一个"索引"来误导。 (虽然我们在这里,但"目标"和"源"或"输入"和"输出"的含义要比" s1"和" s2"少得多。选择不言自明的代码不需要太多注释。变量名称。)


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

例如

1
2
3
4
5
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()(如其他答案中所述),但可能不会很多。


您可能具有以下功能。

1
2
3
4
5
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));
}

可以如下使用:

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

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

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


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

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

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

1
2
3
4
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