Как перевести uint8_t в int?

MrNikto

✩✩✩✩✩✩✩
12 Сен 2021
44
0
Всем привет. В ардуино и C++ я новичок и много не знаю. Сейчас работаю с модулем DS1307 и пользуюсь библиотекой iarduino_RTC.
Хочу перевести часы и минуты в секунды. Для этого часы умножаю на 3600, а минуты на 60, но часы и минуты возвращаются в формате uint8_t и когда я умножаю, возвращается 0. Как можно перевести uint8_t в int или перевести часы в секунды
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
@MrNikto, этот код даст нуль только в одном случае - если величина watch.Hours равна нулю. Ищите ошибки в коде, uint8 тут не при делах.
Для проверки напечатайте в Сериал эту величину отдельно:
Serial.println(watch.Hours );
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
удивительно.
Не понимаю.
13*3600 = 46800
то есть результат без всяких преобразований помещается в uint16.
Допустим, он преобразуется в знаковый инт - тогда должно быть -14033.
Но никак не ноль!

Кто-нибудь обьясните этот феномен?
Хотя я думаю, что тип переменных тут непричем, ошибка у ТС где-то в другом месте.
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Serial.print() - перегруженная функция
посмотрел исходник, все стало еще более непонятным.
При вызове print(unsigned int n) вызывается print( (unsigned long) n), то есть все равно никакого нуля тут быть не может.

У кого под рукой ардуина, попробуйте следующий код:
uint8_t a = 13;
Serial.print(a * 3600);

Неужто ноль напечатает?
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Видимо так:
watch.Hours это байт.
а ссылка идет на старший байт (видимо!) , т.е. 00 00 12 С0.
Ну и 1-ый байт это 0, он и выводится.
Но это скорее предположение как бы это могло быть.
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Это предположение плохо вяжется с исходным кодом print() - передача переменной на печать идет по значению, а не по ссылке.

Но я сначала доберусь домой и попробую, действительно ли Serial.print(13*3600) выдает в мониторе порта ноль. Что-то я не очень в это верю.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Действительно, предположение не верное. Не знаю что там. Но надо смотреть переменную часов.
Вот такой код
C++:
  Serial.begin(115200);
  uint8_t a=13;
  Serial.println(a*3600);
  Serial.println((uint16_t)a*3600);
  Serial.println((uint32_t)a*3600);
  Serial.println(13*3600);
  int8_t b=13;
  Serial.println(b*3600);
  Serial.println((uint16_t)b*3600);
  Serial.println((uint32_t)b*3600);
Такой результат:
18:51:42.249 -> -18736
18:51:42.249 -> 46800
18:51:42.249 -> 46800
18:51:42.249 -> -18736
18:51:42.249 -> -18736
18:51:42.249 -> 46800
18:51:42.249 -> 46800
 
  • Лойс +1
Реакции: bort707

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
А теперь интереснее! Обратите внимание, что второе число знаковое!
C++:
struct m_test
{
  uint8_t tmp1:4;
  int8_t tmp2:4;
};

void setup() {
  Serial.begin(115200);
  m_test a;
  a.tmp1=0;
  a.tmp2=13;
  Serial.println(a.tmp1*3600);
  Serial.println((uint16_t)a.tmp1*3600);
  Serial.println((uint32_t)a.tmp1*3600);
  int8_t b=13;
  Serial.println(a.tmp2*3600);
  Serial.println((uint16_t)a.tmp2*3600);
  Serial.println((uint32_t)a.tmp2*3600);
}
19:00:51.071 -> 0
19:00:51.071 -> 0
19:00:51.071 -> 0
19:00:51.071 -> -10800
19:00:51.071 -> 54736
19:00:51.071 -> 4294956496
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Йес, я все-таки был прав! Спасибо!


@MrNikto, признавайтесь, что вы там намутили , ваша строчка
Serial.println(watch.Hours * 3600);
не могла печатать ноль
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Второй тест может хз. чего наумутить. Я взял стукртуру 1 байт, а если ее взять 4 как в часах ? там очень удобно делать на структурах , т.к. все раскидано по битам. Т.е. для чистоты эксперимента надо брать структуру времени и выводить ее. Не исключаю, что при каких то вариантах может быть 0, но я в этом сомневаюсь.

Не, должно быть все ровно, во всяком случае у меня получился ожидаемый результат как и на простом числе.
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
А теперь интереснее!
знаковое с беззнаковым в общем битовом поле, да еще потом преобразованное в другую размерность?:) - доктор, ну и картинки у вас :)
И дажи при таких извращениях ноль на выходе получается только если ноль на входе, а значит ТС, мягко говоря, соврал.
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
Если интересуют конкретные детали, то описано здесь https://en.cppreference.com/w/c/language/conversion

4) Otherwise, both operands are integers. Both operands undergo integer promotions (see below); then, after integer promotion, one of the following cases applies:
  • If the types are the same, that type is the common type
Integer promotions

Integer promotion is the implicit conversion of a value of any integer type with rank less or equal to rank of int or of a bit field of type _Bool, int, signed int, unsigned int, to the value of type int or unsigned int

If int can represent the entire range of values of the original type (or the range of values of the original bit field), the value is converted to type int. Otherwise the value is converted to unsigned int.
Нужное выделено мной.

То есть тип слева - uint8_t проомутится до int, тип справа тоже int - результат int
 
Изменено: