6
votes

Comment puis-je copier un modèle de répétition dans un tampon de mémoire?

Je veux écrire un modèle répété d'octets dans un bloc de mémoire. Mon idée est d'écrire le premier exemple du motif, puis de le copier dans le reste du tampon. Par exemple, si je commence avec ceci: xxx pré>

après, je veux que cela ressemble à ceci: p> xxx pré> p> Je pensais pouvoir utiliser memcpy code> pour écrire à des régions intersectives, comme ceci: p> xxx pré>

La norme ne spécifie pas de quel ordre la copie se produira, donc si une certaine implémentation fait Il copie dans l'ordre inverse, il peut donner des résultats différents: P>

ptr: 123412340000


10 commentaires

Si je comprends bien, vous voulez le motif entre PTR et PTR + 4 pour être répété jusqu'à 8 octets? Si tel est le cas, vous n'obtiendrez pas ce que vous voulez de memmove ni memcpy .


@zneak, série memcpy fera cela, mais je ne sais pas si sa série


@Dani Que signifie "série" Memcpy?


@Dani, une implémentation spécifique de memcpy peut faire cela, mais un tel cas d'utilisation a un comportement non défini. Vous pouvez rouler votre propre fonction qui fait exactement cela.


Ce n'est en fait pas un duplicata. Je vote pour rouvrir; Je n'ai pas compris la question au début.


@CnicUtar, si une copie d'octets-per-octet se produit avec son exemple, le modèle de 4 octets sera répété sur 8 octets à la fois, au lieu de seulement 4. C'est ce qu'il veut.


L'astuce que vous essayez d'utiliser (multiplier un modèle en utilisant memcpy ) est un peu connu. Cependant, cela ne fonctionne pas conformément à la norme C. Vous ne pouvez pas utiliser memcpy comme celui de la norme C. Il n'est pas garanti de fonctionner.


Je vote pour rouvrir parce que OP veut réellement quelque chose de très différent de ce qui a été demandé. Voir mon commentaire sur la réponse de Ninefingers. Aussi -1 à la question d'être incertain.


@Andreyt: De plus, cela n'a aucun sens. Qu'est-ce qui détermine l'intervalle à laquelle le motif se propage? Très probablement, la taille optimale de copie de l'unité pour la machine spécifique (pas nécessairement uniquement l'ISA) que vous exécutez le programme.


La question est-elle plus claire maintenant, @R ..? Sinon, veuillez éditer plus loin.


6 Réponses :



-1
votes

Pourquoi ne pas simplement allouer un tampon de 8 octets, déplacez-le là-bas, puis revenez-le à l'endroit où vous le voulez? (Comme @CNICUTAR dit, vous ne devriez pas avoir de superposition d'espaces d'adresse pour memcpy.)


1 commentaires

Ce que Memmove fait, et j'ai besoin d'un résultat différent.



0
votes

ancienne réponse

vous voulez Memmove () . Description complète:

La fonction Memmove () doit copier N octets de l'objet pointé par S2 dans l'objet pointé par S1. La copie a lieu comme si les n octets de N octets de l'objet pointé par S2 sont d'abord copiés dans une matrice temporaire de n octets qui ne chevauchent pas les objets pointés par S1 et S2, puis les n octets de la matrice temporaire sont copiés dans l'objet pointé par S1.

à partir du memcpy () Page:

Si la copie a lieu entre des objets qui se chevauchent, le comportement n'est pas défini.

Vous devez utiliser Memmove () de toute façon. C'est parce que le résultat de l'utilisation de memcpy () n'est pas fiable de quelque manière que ce soit.

bits pertinents à la question réelle

Vous demandez memcpy (PTR + 4, PTR, 8); qui dit copier 8 octets de PTR et mettez-les à PTR +4 . PTR est 123400000000, les 8 premiers octets sont 1234000, ce qui le fait: xxx

Vous devez appeler: XXX

Pour réaliser ce que vous êtes après. Ou mettre en œuvre un équivalent. Cela devrait le faire, mais il n'est pas testé et équivaut à memcpy; Vous aurez besoin d'ajouter le tampon temporaire supplémentaire ou d'utiliser deux zones de mémoire non chevauchant. xxx


4 commentaires

Impossible d'utiliser Memmove, il ne produit pas le résultat que je veux


@Dani je vois ce que je pense que vous en arrivez. Vous do veux MemMove , mais vous devez l'utiliser légèrement différemment. Voir Modifier.


Avec les exigences modifiées de OP, MemMove n'est pas nécessaire. OP veut simplement vouloir écrire à plusieurs reprises le même motif 32 bits (?) Sur tout le tampon. Pour cela, un MEMCY (code> (Notez que les régions ne se chevauchent pas maintenant) pour chaque 32 bits, ou wmemset (si Tailleof (wchar_t) = = 4 ) fera le travail très bien.


@R .. J'ai mis à jour ma réponse, tu as raison. Je suis allé avec le Memcpy répété, car c'est ce que j'avais avec Memmove.



5
votes

Il n'y a pas de fonction standard pour répéter un modèle d'octets sur une plage de mémoire. Vous pouvez utiliser la famille Memset_Pattern * code> Fonction pour obtenir des motifs de taille fixe; Si vous avez besoin de la taille pour varier, vous devrez rouler le vôtre.

void byte_copy(void* into, void* from, size_t size)
{
    for (size_t i = 0; i < size; i++)
        into[i] = from[i];
}


6 commentaires

On dirait que vous venez de reimplément memcpy () là, lequel est standard.


@Jonathan GRYNSPAN Il y a une différence subtile: cette fonction a un comportement bien défini lorsque dans + taille et de + taille chevauchement. memcpy , d'autre part, ne le fait pas.


Par exemple, une implémentation optimisée memcpy pourrait choisir de lire et d'écrire des morceaux de 4 à 8 octets à la fois pour aller plus vite. Dans un tel cas, si les zones de mémoire se chevauchent, cette implémentation optimisée ne se comporterait pas nécessairement de la même manière que la mienne.


True, mais dans ce sens, il s'agit toujours de memcpy () , car le comportement de memcpy () dans ce cas est indéfini.


Si vous voulez simplement dire que j'ai implémenté une version de base de l'algorithme MemcPy , nous sommes tous deux d'accord (bien que vous ne puissiez pas utiliser cette implémentation en tant que remplacement d'une liste déroulante pour memcpy , parce que c'est censé renvoyer une copie de la mémoire originale). Autre que cela, ma mise en œuvre diffère de la norme memcpy dans le fait que son comportement est défini lorsque les régions de mémoire se chevauchent et que nous ne pouvons pas utiliser la norme memcpy précisément parce qu'il n'a pas Cette garantie.


En effet, je pense que nous sommes d'accord ici. :)



2
votes

La réponse C ++ pour toutes les plateformes est STD :: Fill_N (destination, Élépée, ElementValue).

Pour ce que vous avez demandé: P>

short val = 0x1234;
std::fill_n(ptr, 3, val); 


2 commentaires

std :: Fill_N () prend une référence pour son troisième paramètre, pas un pointeur, il me semble donc que cette réponse est fausse, non? Cela remplira la mémoire pointée par PTR avec trois copies consécutives du pointeur sur val , pas la valeur de val . Ou suis-je trompé?


@Bhaller merci d'avoir souligné l'erreur dans mon exemple. Je l'ai réparé mais, peu importe, Fill_n est toujours la bonne solution.



0
votes

Vous pouvez le faire en copiant une fois, puis memcpy tout pour copier les octets suivants et répéter cela, il est mieux compris dans le code: xxx

i aspiré; C'est aussi rapide que le memset régulier pour un grand nombre de répétitions , et le source_size est assez dynamique sans beaucoup de pénalité de performance aussi. < / p>


0 commentaires