Я пытаюсь пройти через массив 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
Ответ 1 · рейтинг 3 · John Bollinger
У вас, очевидно, есть как минимум три проблемы:
- Вы используете побитовое "или" (
|) вместо побитового "и" (&).
- Вы используете
data вместо элемента data. Ваше конкретное использование не должно даже компилироваться, поскольку указатели не являются допустимыми операндами для побитовых арифметических операторов.
- Вам не удается сдвинуть данные/замаскированные данные.
Вы также утверждаете в комментариях к другому ответу, что даже после исправления этих ошибок вы получаете вывод со многими ведущими нулями. Я не могу воспроизвести этот результат с помощью 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 для соответствия.
Ответ 2 · рейтинг 2 · Ingo Leonhardt
Самое простое, что вы можете сделать, если хотите иметь однобайтовые значения, это сдвинуть вправо 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;
}
}