I've turned your code into a complete compilable example. I also added a third array of a 'normal' char
which on my environment is signed.
#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;
}
My results were what I expected.
c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20
As you can see, only when the array is of a signed char type do the 'extra' ff
get appended. The reason is that when memcpy
populates the array of signed char
, the values with a high bit set now correspond to negative char
values. When passed to printf
the char
are promoted to int
types which effectively means a sign extension.
%x
prints them in hexadecimal as though they were unsigned int
, but as the argument was passed as int
the behaviour is technically undefined. Typically on a two's complement machine the behaviour is the same as the standard signed to unsigned conversion which uses mod 2^N arithmetic (where N is the number of value bits in an unsigned int
). As the value was only 'slightly' negative (coming from a narrow signed type), post conversion the value is close to the maximum possible unsigned int
value, i.e. it has many leading 1
's (in binary) or leading f
in hex.