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é?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top