Изменение типа одной переменной кардинально меняет размер компиляции

У меня есть набросок, содержащий следующий метод:

// Записывает нули на весь экран, очищая его:
void clearScreen(uint8_t val) {
  setDrawArea(0x00, 0x7f, 0x00, 0x07); // полный экран
  SSD1306.ssd1306_send_data_start();
  for (int c = 0; c < 128 * 8; c++) {
    SSD1306.ssd1306_send_byte(val);
  }
  SSD1306.ssd1306_send_data_stop();
}

Весь скетч компилируется с размером 6730 байт. Во время рефакторинга кода я по ошибке изменил "c" на uint8_t. После этого я скомпилировал в 4124 байта. Это происходит из-за того, что компилятор распознает, что условие цикла никогда не будет достигнуто, и отсекает весь код позади, или это какое-то странное событие оптимизации? Я спрашиваю, потому что не могу сейчас протестировать скетч.

, 👍1


1 ответ


Лучший ответ:

2

Не имея возможности доказать это (поскольку у меня нет ваших библиотек, а вы привели лишь небольшую часть наброска), я думаю, что происходит следующее:

user3629249 наполовину прав. Если изменить c на тип uint8_t, у него будет только 8 бит (отсюда и название), поэтому его максимальное значение будет 255. Когда вы добавите к этому значению 1, переменная переполнится и вернется к 0. Это нормальное поведение при переполнении, как при использовании регистров таймера Arduinos. (Здесь нет неопределенного поведения). Поэтому максимальное значение, которого может достичь c, равно 255.

При сравнении с большим литералом значение c повышается до правильного типа, так что два значения можно сравнивать. Но переменная, которая находится на максимуме 255, всегда меньше, чем 128*8. Так что у вас здесь бесконечный цикл. Компилятор может это увидеть и не включает функции из остальной части clearScreen(), так как это недостижимый код.

В целом ваш код не будет работать так, как задумано с uint8_t. Вам нужен больший тип, который может содержать весь диапазон, с которым вы работаете. И эта оптимизация не странная, а очень разумная, поскольку в этом случае вам действительно не нужна остальная часть clearScreen().

,