Вчера, или даже уже сегодня в районе полуночи, уже плохо соображая, в процессе изготовления подарка на ДР дяде, столкнулся с недостатком опыта в математике и соответствующем мышлении. Задача: для перебора битов в массиве чисел, нужно организовать такую последовательность цифр - 0..7, 0..7, 7..0, 7..0 и всё заново. т.е. два раза от 0 до 7 бита пройтись, два раза в обратном порядке и так по кругу. Не думая, по привычке сворганил всё на IF-ах. Спойлер: Получилось это Код (C++): int8_t pos; int8_t znak = 1; uint8_t steps; void setup() { Serial.begin(9600); } void loop() { if (pos == 8) { if (steps) { znak = -1; steps = !steps; pos = 7; } else { pos = 0; steps = !steps; } } Serial.println(pos); delay(100); pos = pos + znak; if (pos == -1) { if (steps) { znak = 1; steps = !steps; pos = 0; } else { pos = 7; steps = !steps; } } } Посмотрел и ужаснулся ... Переписал всё на конченных автоматах Спойлер: Вышло так Код (C++): int8_t pos = -1; uint8_t steps = 1; void setup() { Serial.begin(9600); } void loop() { switch (steps) { case 1: case 2: pos++; if (pos == 8) {pos = 0; steps++;} if (steps == 3) {pos = 7;} break; case 3: case 4: pos--; if (pos == -1) {pos = 7; steps++;} if (steps == 5) {pos = 0; steps = 1;} break; } Serial.println(pos); delay(100); } Уже лучше ... хотел вчера ночью тему создать, но вставать рано, лёг ... Сегодня на работе осенило, какой я тупой и сделал так Спойлер: Последние потуги Код (C++): uint8_t pos = 8; int8_t znak = 1; void setup() { Serial.begin(9600); } void loop() { Serial.println(pos % 8); delay(100); pos = pos + znak; if (pos == 24) { pos = 23; znak = -1;} else if (pos == 7) { pos = 8; znak = 1;} } На это уже смотреть можно. Но не оставляет чувство, что можно сделать лучше ... что скажете, комрады?
Не, else там нужен, ибо красота кода не в его размере, а в его оптимальности . Пускай даже на одну проверку один раз из 16, даже с delay . Но одновременно pos не может быть и 24 и 7. А так, мне кажется, более читаемо: Спойлер: Код Код (C++): #define STEPS_UP 2 #define STEPS_DOWN 2 int8_t pos = 0; int8_t znak = 1; void setup() { Serial.begin(9600); } void loop() { Serial.println(pos & 7); delay(100); pos += znak; if (pos == STEPS_UP*8) { pos = STEPS_DOWN*8-1; znak = -1;} else if (pos < 0) { pos = 0; znak = 1;} } Надо только проверить
Этот делэй для проверки Я на даче, отдыхаю Кстати, заметил, что если pos определена как беззнаковая, то прошивка на выходе весит на 40 (точно не помню) байт меньше. Это как так выходит?
Какая-то проверка на выход за пределы не осуществляется. Тут же все просто - чтобы писать эффективный код, необходимо четко представлять, какие флаги и когда поднимаются в системном регистре у МК.
Я себе бы ответил так: "компилятор" компилирует и оптимизирует. Оптимизация включает в себя изменение кода на "шаблоны". Спойлер: пример цикл от 0 до n преобразуется в цикл от 0 до n/4 а внутри цикла операции дублируются 4 раза было Код (C++): for(int i=0; i<n; i++) {a[i]=a+i} стало Код (C++): for(int i=0; i<n/4; i=i+4) {a[i]=a+i; a[i+1]=a+(i+1); a[i+2]=a+(i+2); a[i+3]=a+(i+3)} пределы цикла надо аккуратнее проверить. Работа со знаком числа может занимать пару доп. операций на всякие проверки.
Пару. И со знаком, без знака, обычно, нет принципиальной разницы. Разница есть, когда появляется float.
Я тоже на даче. Погода хорошая, ходим купаться! Стало интересно, по поводу знаковой без знаковой переменной, скомпилировал Ваш код под Uno и свой. Ваш код с беззнаковой: Код (Text): Скетч использует 1744 байт (5%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 190 байт (9%) динамической памяти, оставляя 1858 байт для локальных переменных. Максимум: 2048 байт. Код моего варианта: Код (Text): Скетч использует 1738 байт (5%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 189 байт (9%) динамической памяти, оставляя 1859 байт для локальных переменных. Максимум: 2048 байт.
Только добрался до компьютера. Всё проверил, работает! Ваш & тоже занимает места после компиляции меньше чем мой %. Плюс мне приходится присваивать pos = 8, это ещё пара байт Спасибо! Прихватизирую ваш вариант!
Похоже логика организовать массив констант и тупо перебрать никому в голову не пришла. Этот метод проще и компактнее.