web-dev-qa-db-fra.com

memcpy avec startIndex?

Je souhaite copier du contenu d'une longueur spécifique d'un tampon à un autre à partir d'un point de départ spécifique. J'ai vérifié memcpy() mais cela ne prend que la longueur du contenu à copier tandis que je veux aussi spécifier l'index de départ.

Y a-t-il une fonction qui peut le faire ou existe-t-il une bonne approche pour le faire avec la fonction memcpy existante?

34
soloasylum

Je préfère toujours la syntaxe

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

Ajoutez simplement l'offset que vous voulez à l'adresse du tampon.

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

Cela copie 10 octets à partir de abuff [5] vers bbuff.

23
anon

Ajoutez simplement l'offset aux adresses. Par exemple, si vous vouliez copier le tampon en commençant par le Nième octet:

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

Cela copiera dans le destination. Si vous souhaitez également décaler la destination - ajoutez le décalage aux deux:

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

Un index n'est pas requis car vous pouvez simplement mettre à jour le pointeur source par le nombre d'octets spécifié. Le wrapper suivant devrait faire l'affaire

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

Ce site a besoin d'un moyen pour permettre des suivis anonymes en plus des réponses anonymes.

Pourquoi, plus d'une fois, je vois cette affirmation insensée qu'un "index" doit être en unités de 1 octet? C'est tout le contraire de la convention. Un "index" est généralement symbolique, une mesure dont le décalage physique des octets est déterminé par la taille de l'élément dans le tableau (ou vecteur, qui peut même ne pas avoir la disposition physique d'un tableau, mais memcpy () n'a pas non plus d'importance cours).

Ainsi, le 5ème élément d'un tableau a "index" 5, mais:

  • Si le tableau est de type char, alors le décalage d'octet de cet "index" est 5.
  • Si le tableau est de type court (sur x86), alors le décalage d'octet de cet "index" est 10.
  • Si le tableau est de type int (sur x86), alors le décalage d'octet de cet "index" est 20.
  • Si le tableau est le type d'un grand objet de 48 octets, alors le décalage en octets de cet "index" est 240.

La manière correcte d'accéder à cet élément spécifique est un point latéral. L'important est que vous compreniez la différence, que vous en choisissiez une et que vous fassiez le bon code.


Concernant le sens des mots, je préfère de loin lire:

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

que:

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

Je trouve l'idée qu'un vide * complètement générique pourrait avoir un "index" trompeur. (Pendant que nous sommes ici, "dest" et "source" ou "in" et "out" seraient beaucoup moins ambigus que "s1" et "s2". Le code n'a pas besoin d'autant de commentaires lorsque vous choisissez une explication noms de variables.)

1
Matthew

Augmentez simplement votre pointeur sur votre index de départ.

Exemple

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);

Qu'en est-il de l'utilisation des collections STL pour éviter les erreurs d'accès à la mémoire?

1
Edouard A.

Ajoutez simplement l'index à l'adresse du tampon et passez-le à memcpy() comme paramètre source, par ex. copie du 3e élément du tampon b

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

Tenez également compte du type d'éléments dans le tampon, le paramètre de longueur (3e) de memcpy () est en octets, donc pour copier 4 ints, vous devez mettre 4 * sizeof (int) - qui sera probablement 16 (sur un 32 bits Mais le type n'a pas d'importance pour l'adresse de début, en raison de l'arithmétique du pointeur:

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
0
CsTamas

Si vous utilisez c ++, il est probablement préférable d'utiliser std :: copy () au lieu de memcpy (). std :: copy peut prendre les pointeurs aussi facilement que les itérateurs.

par exemple.

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 );

Comme avec memcpy (), il est de votre responsabilité de vous assurer que les pointeurs sont valides.

REMARQUE. Si votre utilisation est critique en termes de performances, vous pouvez trouver un memcpy () comme détaillé dans les autres réponses plus rapidement, mais probablement pas beaucoup.

0
Andy J Buchanan

Vous pourriez avoir une fonction comme ci-dessous.

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));
}

Il peut être utilisé comme ci-dessous:

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

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

Vous devez vous assurer que le tampon de destination a suffisamment de place pour copier les éléments.

0
Indy9000