Понимание # 1 здесь - то, что AVR - ядро технологии 1980-1990-ых.Это не 64-битный ПК, который жует 64-битные числа на завтрак, а крайне неэффективный 8-битный MCU.Таким образом:
- Ему нравится 8-битная арифметика.
- Он будет бороться с 16-разрядной арифметикой, выполняя трюки с 16-разрядными индексными регистрами, двойными аккумуляторами или любыми 8-разрядными основными трюками, которые он предпочитает делать.
- Для выполнения 32 потребуется буквально целая вечностьбитовая арифметика, вызывая встроенные библиотеки программного обеспечения.
- Вероятно, он растает через пол при попытке 64-битной арифметики.
Прежде чем делать что-либо еще, вам нужно избавиться от всех64-битная арифметика и радикально минимизирует использование 32-битной арифметики.Период.В вашем коде не должно быть ни одной переменной uint64_t
, или вы делаете это очень-очень неправильно.
С этим открытием также следует, что все 8-битные MCU всегда имеют тип int
, который16 бит
В коде 1<<current_bit
целочисленная константа 1
имеет тип int
.Это означает, что если current_bit
равно 15 или больше, вы будете сдвигать биты в знаковый бит этого временного int
.Это всегда ошибка.Строго говоря, это неопределенное поведение.На практике вы можете получить случайную смену знака своих чисел.
Чтобы избежать этого, никогда не используйте никакие формы побитовых операторов для чисел со знаком.При смешивании целочисленных констант, таких как 1
, с побитовыми операторами, измените их на 1u
, чтобы избежать ошибок, подобных упомянутой.
Если кто-нибудь знает более эффективный / компактный способ извлеченияодин бит из переменной, я был бы очень признателен, если бы вы могли поделиться
. Самый эффективный способ в C: uint8_t variable; ... if(variable & (1u << bits))
.Это должно привести к соответствующей инструкции «ответвление, если бит установлен».
Мой общий совет - найти дизассемблер вашей цепочки инструментов и посмотреть, какой машинный код на самом деле сгенерировал код C.Вам не нужно быть гуру ассемблера, чтобы прочитать его, достаточно заглянуть в набор .