Да, не подумал об этом. Спасибо!
К тому же 2 байта для fract многовато.
const uint8_t fract = abs(_value) % _del;
Да, не подумал об этом. Спасибо!
К тому же 2 байта для fract многовато.
const uint8_t fract = abs(_value) % _del;
Я там “дописку” сделал как раз про то, что Вы сейчас написали Обязательно прочитайте, не пропустите. И предложенный мною пример попробуйте. Это важно.
Результат: 6538.0
Я в шоке. Попробую сам разобраться…
Во!
Я, с вашего позволения добавлю этот пример в ту статью про “карту граблей”. Очень уж он удачный получился. Ничего?
Конечно. Очень полезная статья про смешивание типов.
Вот тут немного запутался.
Типы unsigned и int занимают 2 байта, тип long - 4 байта.
Приведение unsigned к long во втором случае логично. Но, не понимаю, почему в первом случае приведение осуществляется именно к unsigned?
Когда переменная получает значение, которое непредставимо в её типе (например, переменная типа unsigned
получает отрицательное значение или переменная типа int16
получает значение большее, чем 32767) – это приводит к неопределённому поведению (undefined behavior), потому лучший способ не пытаться понимать что там делается, т.к. делаться может всё, что угодно и объяснять это особого смысла не имеет.
В данном случае логика понятна, хотя она и ущербна. В некоторой степени отрицательные величины типа int
являются легальными значениями для типа unsigned
. В том смысле, что если присвоить отрицательный int
переменной типа unsigned
, а потом эту переменную присвоить снова переменной типа int
, ничего не сломается.
Обратное неверно. Если отрицательный unsigned
присвоить переменной типа int
, а потом эту int
-переменную присвоить переменной типа unsigned
, то всё сломается.
#include <Printing.h>
void setup(void) {
Serial.begin(9600);
{
const int iv = -15;
const unsigned uv = iv; // это легальная, обратимая операция
const int ivv = uv; // обращаем её
printVarLn(ivv); // результат вернулся к изначальном -15
}
{
const unsigned uv = -15;
const int iv = uv; // это нелегальная, она необратима
const unsigned uvv = iv;// обращаем её
printVarLn(uvv); // результат улетел куда попало
}
}
void loop(void) {}
Таким образом, можно говорить, что тип unsigned
- объемлющий по отношению к int
. Потому к нему и преобразовывается.
Вот если было бы int32_t
и uint16_t
, то преобразование шло бы к знаковому потому, что на этот раз он “объемлющий”. В этом-то там и грабли, всегда трудно предсказать куда он там начнёт преобразовывать.
Спасибо! Исчерпывающе.