Вопрос, апятьже, к "икспердам"
- Войдите на сайт для отправки комментариев
Ср, 25/03/2020 - 11:42
есть структура из битовых полей, без методов, размером в 1 байт
struct TAHTStatus { public: uint8_t Reserved : 3; bool Calibrated : 1; bool Reserved2 : 1; enMode WorkMode : 2; bool Busy : 1; };
как можно байт ответа устройства привести к типу этой структуры без таких костылей?
TAHTStatus GetStatus(void) { Wire.requestFrom(FDevAddress,1U); // запрашиваем байт статуса uint8_t status = Wire.read(); // читаем его TAHTStatus result; // создаем временный обьект, чтоб его отдать uint8_t *tmp = (uint8_t *)(&result); // применяем костыли *tmp = status; // копируем в них return result; // и возвращаем }
memcpy() наерна можно применить, но это тоже костыли. А static_cast<TAHTStatus>(status) не работает, пишет, нет такова конструктора. Чёртичо, короче, и сбоку бантег. В Delphi хоть absolute есть.
канеш, так memcpy(&result, &status, 1); тоже работает, но ить некрасива же.
reinterpret_cast. Для static_cast нужно правила объявлять.
так он же для пойнтеров только, а у меня оба типа-значения одного размера
Allows any pointer to be converted into any other pointer type
наерна, проще будет в структуру конструктор запилить
Наскока это безопасно?
наерна, проще будет в структуру конструктор запилить
Наскока это безопасно?
С точки зрения COVID-19? Ну руки воткой протри, штоле!
Дет, ты ж нормальный программист, а иногда тебя заносит, аж жуть! ;))) По трезвяку верно?
------------------------
Если под "безопасно" ты понимаешь страховку от неработоспособности в новой версии GCC, то Женя тебе объяснит, что такой страховки не бывает! ;))) В комитете - такие затейники! Даже я краснею, бывает.
Дет, ты ж нормальный программист, а иногда тебя заносит, аж жуть! ;)))
Чойта? Я реально иногда нихрена в этом лжывом С++ не понимаю, не родной он мне, не привыкну всё, что никогда нельзя сказать точно, что сегодня с утра значит оператор присваивания, к примеру. Да и программист из меня - как из авна пуля, особенно в последние годы. :)
Деда, первое, что нужно сделать - это принудительно указать компилеру на выравнивание структуры по границе байта:
В случае, когда у тебя там будет битовых полей и прочей чепухи больше, чем на один байт - ты будешь уверен, что всё идёт последовательно, без выравниваний, которые применяет компилятор так, как ему хочется.
Второе - можно применить побайтовое копирование, отдав это дело на откуп компилятору, и без memcpy:
Я только enMode заменил на uint8_t, т.к. не знаю, чего это за тип у тебя.
Дед, ну, конечно, можно и прямо преобразовывать типы, никто не мешает, только аккуратно. Например, можно написать вот так:
Но я бы так писать не стал. И memcpy тоже не стал бы использовать. Вместо этого я бы сделал из структуры union и использовал бы простое присваивание. Примерно вот так:
Обрати внимание, что структура, которая сидит внутри union не имеет никакого имени. Это важно! Именно это позволяет обращаться к её членам напрямую (например, kaka.Calibrated). Если бы у неё было имя, то пришлось бы тащить его всё время.
Но это половинчатое решение. А как быть с обратной задачей, не впихнуть в твою структуру какое-то значение, а наоборот её значение запихать куда-то? Можно добавить переопределение операторов присваивания и приведения типа, но тут засада - у юнионов операторы не переопределяются. Выход, например, такой - запихать union в ещё одну структуру и уже у неё всё, что надо переопределить (при этом помним про то, что без крайней нужды имена никуда не пихаем!). Получается что-то типа:
На самом деле, можно ещё кучу способов предложить, но такой, вроде, всё, что нужно делает и к полям можно прямо обращаться, типа kaka.Calibrated
Все рассмотренные решения (включая и твоё с memcpy) абсолютно идентичны по ресурсам (память там и быстродействие) - код получается просто одинаковый.
Спасибо, парни, остановился на этом, если подводных камней нет, то меня полностью устра.
Деда, первое, что нужно сделать - это принудительно указать компилеру на выравнивание структуры по границе байта:
Спасибо, я это всегда делаю теперь на уровне спинного мозга, где надо, и где не надо. :)
Спасибо, парни, остановился на этом, если подводных камней нет, то меня полностью устра.
В приведённом примере - подводных камней нет, если меня зрение не подводит. Однако, чем тебя не устраивает reinterpret_cast? В твоём случае - ты жёстко привязываешься к байту. В случае с reinterpret_cast - компилятор сам скопирует в структуру всё, что находится по указателю. Расширил объявление структуры - оно автоматически скопируется из источника, приведённого к типу указателя на структуру. Конечно, и этим способом можно себе ногу прострелить, залазя в память не тудыть.
Короче, делай как нравится, вариантов, как видишь, всегда есть ;)
Спасибо. :-)
На срецтво, дет, на срецтво. Виш кака эпидерсия вакрук, срецтво + перец + агурец = вот нашефсё!!!
В приведённом примере - подводных камней нет, если меня зрение не подводит. Однако, чем тебя не устраивает reinterpret_cast?
Ненавижу звёздочки, скопки и их комбинацыи. :) Пока разберешься, чо к чему относица - уже, глядишь, и плюшевый вхлам.
Обрати внимание, что структура, которая сидит внутри union не имеет никакого имени. Это важно! Именно это позволяет обращаться к её членам напрямую (например, kaka.Calibrated). Если бы у неё было имя, то пришлось бы тащить его всё время.
Вот не знал, категорически блаадарю. :) Иногда так ломает в union struct пхать, именно из-за обилия точек в такой переменной, аж в глазах рябит, теперь знать буду. :) Век живи - а дураком памрёшь.
Понятное дело, мы с моим стратегическим запасом мяса и шерсти теперь столько валерянки накупим...
Скотокот одобряэ.
Хорошо когда белый - все блохи как на ладони. Не то что у моего чёрного.(