MEMCPY Ajoute FF FF FF au début d'un octet
Question
J'ai un tableau qui est comme ceci:
unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
unsigned char array2[6];
Quand j'utilise memcpy:
memcpy(array2, array, 6);
Et imprimez tous les deux:
printf("%x %x %x %x %x %x", array[0], // ... etc
printf("%x %x %x %x %x %x", array2[0], // ... etc
Un imprime comme:
c0 3f e 54 e5 20
Mais l'autre imprime
ffffffc0 3f e 54 ffffffe5 20
Qu'est-il arrivé?
La solution
J'ai transformé votre code en un exemple compilable complet. J'ai également ajouté un troisième tableau d'un «normal» char
qui sur mon environnement est signé.
#include <cstring>
#include <cstdio>
using std::memcpy;
using std::printf;
int main()
{
unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
unsigned char array2[6];
char array3[6];
memcpy(array2, array, 6);
memcpy(array3, array, 6);
printf("%x %x %x %x %x %x\n", array[0], array[1], array[2], array[3], array[4], array[5]);
printf("%x %x %x %x %x %x\n", array2[0], array2[1], array2[2], array2[3], array2[4], array2[5]);
printf("%x %x %x %x %x %x\n", array3[0], array3[1], array3[2], array3[3], array3[4], array3[5]);
return 0;
}
Mes résultats étaient ce à quoi je m'attendais.
c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20
Comme vous pouvez le voir, uniquement lorsque le tableau est d'un type de char signé faire le «extra» ff
être annexé. La raison en est que lorsque memcpy
remplit la gamme de signés char
, les valeurs avec un ensemble de bits élevés correspondent désormais à négatif char
valeurs. Lorsqu'il est passé à printf
la char
sont promus pour int
Types qui signifie effectivement une extension de signe.
%x
les imprime en hexadécimal comme s'ils étaient unsigned int
, mais comme l'argument a été passé comme int
Le comportement est techniquement indéfini. En règle générale, sur une machine de complément de deux, le comportement est le même que la norme signée à la conversion non signée qui utilise l'arithmétique Mod 2 ^ n (où n est le nombre de bits de valeur dans un unsigned int
). Comme la valeur n'était que «légèrement» négative (provenant d'un type signé étroit), après la conversion, la valeur est proche du maximum possible unsigned int
valeur, c'est-à-dire qu'il a beaucoup 1
(en binaire) ou en tête f
en Hex.
Autres conseils
Le problème n'est pas memcpy
(À moins que votre type de char ne soit vraiment de 32 bits, plutôt que 8), il ressemble plus à une extension de signe entier lors de l'impression.
Vous voudrez peut-être changer votre printf pour utiliser explicitement la conversion de char non signée, c'est-à-dire.
printf("%hhx %hhx...", array2[0], array2[1],...);
Aux suppositions, il est possible que votre compilateur / optimiseur soit manipulé array
(dont la taille et le contenu sont connus au moment de la compilation) et array2
différemment, poussant des valeurs constantes sur la pile en premier lieu et poussant à tort le signe étendu des valeurs dans la seconde.
Vous devez masquer les bits supérieurs, car vos caractères seront étendus à int
taille lors de l'appel d'une fonction Varargs:
printf("%x %x %x %x %x %x", array[0] & 0xff, // ..
Le format% x attend un type entier. Essayez d'utiliser le casting:
printf("%x %x %x %x %x %x", (int)array2[0], ...
Edit: Puisqu'il y a de nouveaux commentaires sur mon message, je souhaite ajouter des informations. Avant d'appeler la fonction printf, le compilateur génère du code qui pousse sur la liste des variables de pile des paramètres (...). Le compilateur ne sait rien des codes de format printf et pousse les paramètres en fonction de leur type. printf collecte des paramètres de la pile en fonction de la chaîne de formatage. Ainsi, le tableau [i] est poussé comme char, et géré par printf comme int. Par conséquent, il est toujours une bonne idée de faire la coulée, si le type de paramètre ne correspond pas exactement à la spécification du format, en travaillant avec les fonctions printf / scanf.