Чтение битов из указателя const char
В последнее время я немного путаюсь в указателях const char.
Я получаю сообщение от сервера, которое приходит либо в виде строки в стиле c, либо в виде строки стандартной библиотеки, либо в виде WString:
Я отправляю вниз буфер из 32-битных значений с моего сервера, которые не являются текстом ascii или utf, это просто битовые значения, которые я хочу разобрать и прочитать на стороне esp32:
Я подумал: "О, я просто замаскирую битовые значения 32 бита за раз и сдвину данные вправо, чтобы получить сообщение (в обратном порядке, но все же я могу работать с этим). Проблема, с которой я столкнулся, заключается в том, что я могу сдвигать числа, но не строки или байтовые массивы.
Я написал функцию, позволяющую мне захватить кусок строки 32 бита за раз и преобразовать его в число, используя смещение:
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{
uint32_t payload = 0;
for (uint8_t i = 0; i < 8; i++)
{
payload <<= 0;
payload += data[i + offset];
}
return payload;
}
Но когда я пытаюсь захватить первую пару 32-битных фрагментов, данные не такие, как я ожидал:
void handleGameFrame(const char *data, uint32_t length)
{
uint8_t phaseAndColission = get32BitInt(data, 32);
uint8_t player = getByte(data, 32 * 2);
Serial.print("data: ");
Serial.println(data);
Serial.print("phaseAndColission: ");
Serial.println(phaseAndColission, DEC);
Serial.print("player: ");
Serial.println(player, DEC);
}
урожайность:
Я знаю, что Serial.println(data);
не собирается ничего выводить b/c, это c-строка непечатаемых значений, но другой захват фрагмента не дает мне такого же вывода с моего сервера. Трудно проверить все, не имея возможности увидеть все биты в общем указателе данных, и я думаю, что связал себя в (другом) узле.
Есть ли хороший способ разобрать 32-битные значения из константной c-строки?
@Chris Schmitz, 👍0
Обсуждение1 ответ
Лучший ответ:
Вы написали:
Я написал функцию позволяющую мне захватывать кусок строки по 32 бита за раз и преобразовывать его в число используя смещение
Эта функция почти правильна. Попробуйте это:
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{
uint32_t payload = 0;
for (uint8_t i = 0; i < 4; i++)
{
payload <<= 8;
payload |= data[i + offset];
}
return payload;
}
По сравнению с вашей версией различия заключаются в следующем:
Он считывает 4 байта вместо 8, так как 32 бита-это четыре байта.
Для каждого считываемого байта он сдвигает полезную нагрузку на 8 бит (то есть на один байт) вместо нуля. Сдвиг на ноль не имеет никакого эффекта.
Он использует
|=
вместо+=
: просто микрооптимизация ради 8-битных микроконтроллеров. Это не должно иметь большого значения, если речь идет о 32-битном микропроцессоре.
О боже мой. Я не могу поверить, что пропустил этот сдвиг на ноль :facepalm: Я знаю, что условная проверка for loops также ошибочна, но я не могу поверить, что пропустил ошибку сдвига. Спасибо, что указали на них, а также на побитовую оптимизацию или оптимизацию. Я ценю, что вы нашли время, чтобы исправить эту функцию :луки:, @Chris Schmitz
- форматирование строк в Arduino для вывода
- Проблемы с преобразованием byte[] в String
- Чтение строки, разделенной запятыми
- Использование строки вместо строки C, еще одна попытка затронуть загруженную проблему
- Разделение Serial.readString на массив строк
- GSM-модуль Arduino + строка SMS, отправляющая мусорное значение
- Преобразование JSON в строку для MQTT
- strcmp, похоже, не работает
"это просто битовые значения". Вы имеете в виду, что они просто "uint32_t", на которые указывают с помощью " const char *` ?, @timemage
О, я просто имею в виду, что данные (
const char *
) содержат биты, которые не могут бытьSerial.println
-ed, потому что даже в 8-битной форме они не являются допустимыми символами ascii/utf, поэтому ничто не попадает на монитор., @Chris Schmitzно да, данные-это c-строка байтов, и я знаю, что хочу интерпретировать ее как 32-битные целые числа, я просто не могу понять, как это сделать., @Chris Schmitz
Ну, "с-строка" в основном означает ноль или более не- "\0", за которыми следует "\0". Если какое-либо из ваших чисел случайно имеет нулевой байт в них, это завершит "строку" до конца ваших фактических данных. Например, 0xAA00BB. На самом деле это вовсе не струна. С точки зрения того, как вы получаете из него данные, если они правильно выровнены для uint32_t, вы можете просто
const uint32_t *ui32p = reinterpret_cast<const uint32_t *>(mycharptr);
Если он не выровнен, вы сделаете что-то вроде "memcpy" в массив или отдельные элементы в одну переменную "uint32_t". Здесь нет ничего действительно "Arduino"., @timemageможет потребоваться шестнадцатеричное кодирование значений, чтобы передать их., @dandavis
это похоже на проблему X->Y. "Я получаю сообщение от сервера, которое приходит либо в виде строки в стиле c, либо в виде строки стандартной библиотеки, либо в виде WString" почему?, @Juraj
@Juraj это форматы сообщений, которые дает мне библиотека, которую я использую. Там нет опции только для буфера байтов. Я бы подумал, что c-string является эквивалентом буфера, но есть проблема с терминатором null., @Chris Schmitz