Вопрос

У меня есть массив, который такой:

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

Когда я использую Memcpy:

memcpy(array2, array, 6);

И распечатать их обоих:

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

Один печатает вроде:

c0 3f e 54 e5 20

Но другой печатает

ffffffc0 3f e 54 ffffffe5 20

что случилось?

Это было полезно?

Решение

Я превратил ваш код в полный собранной пример. Я также добавил третий массив «нормального» char который в моей среде подписан.

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

Мои результаты были тем, что я ожидал.

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

Как видите, только когда массив подписанный тип Char, сделайте «дополнительный» ff получить добавление. Причина в том, что когда memcpy заполняет массив подписанного char, значения с высоким набором бита теперь соответствуют отрицательному char ценности. Когда передано printf а char продвигаются на int Типы, которые эффективно означают расширение знака.

%x печатает их в шестнадцатеричном unsigned int, но как аргумент был принят как int Поведение технически не определен. Как правило, на двухместной машине поведение такое же, как и стандартное, подписанное на беспигнированное преобразование, которое использует арифметику MOD 2^n (где n - количество бит значения в unsigned int) Поскольку значение было лишь немного «слегка» отрицательным (исходя из узкого подписанного типа), преобразование после преобразования значения близко к максимально возможным unsigned int ценность, т.е. у него много ведущих 1S (в бинарном) или ведущем f в гекс.

Другие советы

Проблема не memcpy (Если ваш тип Char на самом деле не является 32 битами, а не 8), он больше похож на расширение знака целочисленного знака во время печати.

Возможно, вы захотите изменить свой Printf, чтобы явно использовать конверсию без подписи, т.е.

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

В качестве предположения, возможно, что ваш компилятор/оптимизатор обрабатывает array (Размер и содержимое чьи array2 По -другому, в первую очередь наталкивая постоянные значения в стек и ошибочно выдвигая расширенные знаки во втором.

Вы должны замаскировать более высокие биты, так как ваш Chars будет расширен на int размер при вызове функции Varargs:

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

%x Формат ожидает целочисленного типа. Попробуйте использовать кастинг:

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

РЕДАКТИРОВАТЬ: Поскольку в моем посте есть новые комментарии, я хочу добавить некоторую информацию. Перед вызовом функции PrintF компилятор генерирует код, который нажимает на список переменных стека (...). Компилятор ничего не знает о кодах форматов printf и выдвигает параметры в соответствии с их типом. printf собирает параметры из стека в соответствии с форматированием строки. Итак, массив [i] выдвигается как ЧАР, и обрабатывается Printf как int. Следовательно, всегда хорошая идея сделать литью, если тип параметров не соответствует точно такой спецификации формата, работая с функциями printf/scanf.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top