Pregunta

Tengo una matriz que es así:

unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
unsigned char array2[6];

Cuando uso memcpy:

memcpy(array2, array, 6);

E imprima los dos:

printf("%x %x %x %x %x %x", array[0],  // ... etc
printf("%x %x %x %x %x %x", array2[0], // ... etc

Uno imprime como:

c0 3f e 54 e5 20

Pero el otro imprime

ffffffc0 3f e 54 ffffffe5 20

¿qué sucedió?

¿Fue útil?

Solución

He convertido su código en un ejemplo compilable completo. También agregué una tercera matriz de un 'normal' char que en mi entorno está firmado.

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

Mis resultados fueron lo que esperaba.

c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20

Como puede ver, solo cuando la matriz es de un tipo de char firmado, haga el 'extra' ff Agradecer. La razón es que cuando memcpy pobla la matriz de firmado char, los valores con un conjunto de bits alto ahora corresponden a negativos char valores. Cuando se pasó a printf la char son promovidos a int tipos que significan efectivamente una extensión de signo.

%x los imprime en hexadecimal como si fueran unsigned int, pero a medida que el argumento se pasó como int El comportamiento está técnicamente indefinido. Por lo general, en una máquina de complemento de un dos, el comportamiento es el mismo que el estándar firmado en conversión sin firmar que utiliza la aritmética mod 2^n (donde n es el número de bits de valor en un unsigned int). Como el valor fue solo 'ligeramente' negativo (proveniente de un tipo estrecho firmado), la conversión posterior al valor está cerca del máximo posible unsigned int valor, es decir, tiene muchos liderazgo 1's (en binario) o liderazgo f en hex.

Otros consejos

El problema no es memcpy (A menos que su tipo de char realmente sea 32 bits, en lugar de 8), se parece más a la extensión de signo entero mientras se imprime.

Es posible que desee cambiar su printf para usar explícitamente la conversión de char sin firmar, es decir.

printf("%hhx %hhx...", array2[0], array2[1],...);

Como suposición, es posible que su compilador/optimizador esté manejando array (cuyo tamaño y contenido se conocen en el momento de la compilación) y array2 de manera diferente, empujar valores constantes en la pila en primer lugar y empujar erróneamente los valores extendidos en el segundo.

Debe enmascarar los bits más altos, ya que sus caracteres se extenderán a int tamaño al llamar a una función varargs:

printf("%x %x %x %x %x %x", array[0] & 0xff,  // ..

El formato %X espera el tipo de entero. Intenta usar el casting:

printf("%x %x %x %x %x %x", (int)array2[0], ...

EDITAR: Dado que hay nuevos comentarios en mi publicación, quiero agregar información. Antes de llamar a la función Printf, el compilador genera código que presiona la lista de parámetros de la variable pila de parámetros (...). El compilador no sabe nada sobre los códigos de formato printf y empuja los parámetros de acuerdo con su tipo. Printf recopila parámetros de la pila de acuerdo con la cadena de formato. Entonces, la matriz [i] se empuja como char, y se maneja por printf como int. Por lo tanto, siempre es una buena idea hacer que la fundición, si el tipo de parámetro no coincide exactamente con la especificación de formato, trabajando con funciones printf/scanf.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top