Бывает так, что какое-то действие в программе, надо выполнить ,по условию ,только один раз. Ну ничего, норм. Заводим флаг, выполняем действие , сбрасываем флаг. Затем всё остальноё время продолжаем проверять этот флаг, хотя , это действие уже никогда выполнять не будем.
Например:
void PrintNum(uint8_t num)
{
static bool f = true;
if (f) // <----------- можно ли избежать "пожизненной",
{ //и, после первого раза уже "не нужной" проверки?
Serial.println("===== Превышение уровня чего-то там!!! ===========");
//вывести строку один раз, при
f = false; //первом вызове программы
}
Serial.print( " Время ");
Serial.print( millis());
Serial.print(" мс уровень...");
Serial.println(num);
}
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0));
}
void loop() {
uint8_t number;
number = (uint8_t)random(255);
if (number > 200)
PrintNum(number);//прогамма вызывается, если превышено
// пороговое значение
delay(500);
}
Что происходит: компилятор понимает, что условие if( flag == 0) - маловероятное (unlikely), поэтому при компиляции кода, компилятор переставит код так, чтобы он исполнялся быстрее.
можно через указатели на функции. Тогда роль флага будет выполнять указатель на функцию:
например, у вас есть указатель на функцию func_t function. Указывает на функцию function_with_flag() .
Пользовательский код:
(*function)()
Функция:
int function_with_flag() {
что то там делаем, флага у нас вообще теперь нет, не нужен он
function = function_without_flag; // слекующий вызов function() вызовет уже функцию другую.
}
Сектч:
function(); // вызовет первую функцию
function(); // вызовет уже другую
Заниматься такой оптимизацией только если для этого действительно есть причины (т.е. реально не хватает производительности).
Иногда доходит до того, что после того, как объект класса, извините, прос***ся на растянутом асинхронном этапе старта всеми инициализационными проверками, указатель на него меняется на другой, в котором разделены те же данные, но основной код уже простой.
// ============================================
// 1. ОБЪЯВЛЕНИЕ ТИПА И УКАЗАТЕЛЯ
// ============================================
// Тип: функция, принимает uint8_t, ничего не возвращает
typedef void (*PrintFunc_t)(uint8_t);
// ============================================
// 2. ПРОТОТИПЫ ФУНКЦИЙ (ДОЛЖНЫ БЫТЬ ДО ИСПОЛЬЗОВАНИЯ!)
// ============================================
void PrintWithHeader(uint8_t num);
void PrintWithoutHeader(uint8_t num);
// Теперь компилятор знает о существовании этих функций!
// ГЛОБАЛЬНЫЙ указатель на функцию (хранится в SRAM)
PrintFunc_t g_print_func = PrintWithHeader; // OK, функция объявлена
// ============================================
// 3. ГЛАВНАЯ ФУНКЦИЯ-ДИСПЕТЧЕР
// ============================================
void PrintNum(uint8_t num) {
// ВСЁ! Просто вызываем функцию по указателю.
// Никаких if, никаких проверок!
g_print_func(num);
}
// ============================================
// 4. ПЕРВАЯ ВЕРСИЯ (с заголовком)
// ============================================
void PrintWithHeader(uint8_t num) {
// Печатаем заголовок (это случится только один раз!)
Serial.println("===== Превышение уровня чего-то там!!! ===========");
// КЛЮЧЕВОЙ МОМЕНТ: перенаправляем указатель на ВТОРУЮ функцию
// Теперь g_print_func указывает на PrintWithoutHeader
g_print_func = PrintWithoutHeader;
// Вызываем вторую функцию, чтобы напечатать данные
// (избегаем дублирования кода)
PrintWithoutHeader(num);
}
// ============================================
// 5. ВТОРАЯ ВЕРСИЯ (только данные)
// ============================================
void PrintWithoutHeader(uint8_t num) {
Serial.print(" Время ");
Serial.print(millis());
Serial.print(" мс уровень...");
Serial.println(num);
}
// ============================================
// 6. СТАНДАРТНЫЕ ФУНКЦИИ ARDUINO
// ============================================
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0));
// Убеждаемся, что указатель указывает на ПЕРВУЮ функцию
// (хотя это уже сделано при инициализации)
g_print_func = PrintWithHeader;
}
void loop() {
uint8_t number = (uint8_t)random(255);
if (number > 200) {
// Вызываем функцию-диспетчер
// Внутри неё НЕТ проверок!
PrintNum(number);
}
delay(500);
}
но лично мне нравится через if, постоянно проверять условия, и писать медленный код…)))
толстый вы все врете!)))
я вот сейчас задумался а быстрее ли…
это все проклятый ассемблер которого не знаю, и к которому все сводится…
по идее быстрее… проклятый ассемблер, проклятые такты…)))
Ага. Ну, они не будут прям уж одинаковыми. В одной будет hotpath, а во второй - условие и опять же вызов hotpath из первой функции. Функция с проверкой будет маленькая, а основная - толстенькая
Я бы оставил так, как в первом сообщении написано: и читаемо через год и просто.
Да, скорее это это так. Для Уно/Нано вряд ли чего лучше придумаешь.
Интересно, может, на “крутых” процессорах есть какое-нибудь аппаратное решение? Например, особый тип инструкций, которые выполняются только один раз. А потом уже читаются как “NOP”… Мало ли чего придумать можно.
Ведь необходимость выполнить что-то только один раз довольно часто бывает