Битовая маска для получения отдельных байтов

Я пытаюсь пройти через массив uint64_t

ie:

const uint64_t data[] =
{
    0x0000000000000000,
    0x1111111111111111,
    0x2322323232323232
}

Из этого я хотел бы пройтись по каждому индексу в массиве и по каждому индексу, распечатать значение каждого байта. Я думаю, что это можно сделать с помощью битовой маски, но я не могу понять это правильно... Пока у меня есть это:

static const int indices = sizeof(data) / sizeof(uint64_t);
uint64_t mask;

for(int i= 0; i < indices; i++)
{
    mask = 0xff;
    for(int byte = 0; byte < 8; byte++)
    {
        printf("index[%d], byte[%d]: 0x%02x\n", i, byte, data | mask);
        mask = mask << 8;
        printf("mask: 0x%016lx\n", mask);
    }
}

Мой вывод соответствует ожиданиям для маски. Он сдвигает 8 бит (1 байт) в каждом цикле. Однако побитовое сравнение данных глупо. Побитовое И, кажется, работает правильно, однако формат не работает. Я ищу операторы печати, которые просто содержат значение байта, а не значение uint64_t, как сейчас. Я думаю, что наличие маски в виде uin64_t мешает печати однобайтового значения, но я не уверен, как это исправить. Я получаю такой отзыв: data[1] byte[1]: 0x1100, но хочу получить свои данные в виде: data[1] byte[1]: 0x11


person kennedyl    schedule 12.07.2016    source источник
comment
Я добавил тег C к вашему вопросу, так как похоже, что вы используете C (который я не использовал около 10 лет... Сейчас я уйду).   -  person Tim Biegeleisen    schedule 12.07.2016
comment
Ах, совершенно разнесены, что. Спасибо!   -  person kennedyl    schedule 12.07.2016
comment
Какое побитовое И, у вас там ИЛИ   -  person harold    schedule 12.07.2016
comment
Спасибо, Гарольд... по-видимому, мне нужно лучше обновлять, так как я сам ловлю вещи. Я заметил это через пару минут после публикации. У меня это работает сейчас ... Предлагает ли этикет stackoverflow редактировать мой исходный почтовый код или делать новый комментарий / ответ?   -  person kennedyl    schedule 12.07.2016
comment
@kennedyl отредактируйте, возможно, оставьте комментарий, чтобы не делать ответы нелогичными.   -  person harold    schedule 12.07.2016


Ответы (2)


У вас, очевидно, есть как минимум три проблемы:

  1. Вы используете побитовое «или» (|) вместо побитового «и» (&).
  2. Вы используете data вместо элемента data. Ваше конкретное использование не должно даже компилироваться, поскольку указатели не являются допустимыми операндами для побитовых арифметических операторов.
  3. Вам не удается сдвинуть данные/замаскированные данные.

Вы также утверждаете в комментариях к другому ответу, что даже после исправления этих ошибок вы получаете вывод со многими ведущими нулями. Я не могу воспроизвести этот результат с помощью GCC, но я заметил, что для дескриптора поля важно указать правильный тип аргумента. Ваш аргумент - это uint64_t, и в большинстве систем C он не соответствует unsigned int, чего ожидает дескриптор поля x, когда не указаны модификаторы длины. Если дополнительные начальные нули представлены даже тогда, когда все совпадает правильно, возможно, ваша реализация x выводит представление всех байтов без усечения начальных нулей. В этом случае вы можете попробовать указать аргумент как (и фактически сделать так) unsigned char.

Собрав все это вместе, вы хотите что-то вроде этого:

for (int i = 0; i < indices; i++)
{
    for(int byte = 0; byte < 64; byte += 8)
    {
        printf("index[%d], byte[%d]: 0x%02hhx\n", i, byte,
            (unsigned char) ((data[i] >> byte) & 0xff));
    }
}

Это сдвигает данные, чтобы сопоставить их с маской, вместо того, чтобы сдвигать маску для выбора данных, потому что последнее в любом случае потребует смещения результата. Я предполагаю, что индексация и использование правильного оператора не нуждаются в дополнительных пояснениях.

Однако обратите внимание также на дескриптор поля и приведение. %02hhx говорит, что поле должно быть заполнено нулями (0) и иметь ширину не менее двух символов (2). Соответствующий аргумент имеет тип целого числа без знака, который должен быть представлен в шестнадцатеричной форме (x), и, в частности, это unsigned char (hh). Соответствующий аргумент приводится к unsigned char для соответствия.

person John Bollinger    schedule 12.07.2016

Самое простое, что вы можете сделать, если хотите иметь однобайтовые значения, это сдвинуть вправо data вместо сдвига mask. Как правильно заметил @harold, «обработка» байта с помощью 0xff не имеет смысла.

for(int i= 0; i < indices; i++)
{
    uint64_t val = data[i];
    for(int byte = 0; byte < 8; byte++)
    {
        printf("index[%d], byte[%d]: 0x%02x\n", i, byte, val & 0xff );
        val >>= 8;
    } 
}
person Ingo Leonhardt    schedule 12.07.2016
comment
Кстати, ((val & 0xff) | 0xff) == 0xff - person harold; 12.07.2016