natsu 0 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба Добрый день, Столкнулся с ситуацией, когда компилятор отказывается считать константу на этапе компиляции, но зато злобно выдает предупреждение о ее значении. Подскажите, плиз, как избавиться от предупреждения в этом конкретном месте либо как заставить компилятор считать значение. Имеется файл определений .h (не в моей власти) ----------------- #define volt (630.5) ... #define volt_max (volt/0.707) В моем .c -------------- #if volt_max > 1000 вызывает ошибку error: floating point literal in preprocessor expression а если написать if(volt_max > 1000.0) .. то предупреждение warning: code will never be executed [-Wunreachable-code] Вот как с этим бороться? А ведь дальше у меня ветвление в зависимости от логарифма подобной константы, которое правильно было бы сделать на этапе компиляции, но похоже компиляторы еще не достигли такого уровня просветления чтобы считать логарифмы на этапе компиляции.. Или я ошибаюсь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 2 hours ago, natsu said: то предупреждение warning: code will never be executed [-Wunreachable-code] Все правильно он ругается, т.к. значение volt известно еще на этапе компиляции и проверки условия if в коде не будет. 2 hours ago, natsu said: Вот как с этим бороться? Бороться с комиплятором бесполезно, только наделаете новых граблей. Если уж начали применять препроцессор (#define), то применяйте его и для условий: #if И вообще, константы объявляются через ключевое слово const, а #define - это по сути "замена" по коду. Т.е. достаточно сделать так: const float volt = 630.5f; const float volt_max = volt/0.707; ... if (volt_max > 1000.0) .... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
natsu 0 10 апреля, 2022 Опубликовано 10 апреля, 2022 (изменено) · Жалоба 1 час назад, Forger сказал: Если уж начали применять препроцессор (#define), то применяйте его и для условий: #if Так ведь не получается с дробными числами! Использование const заставит вынести константы (!) из заголовка в отдельный файл и вместо использования константы будет обращение к ячейке памяти, значение которой вообще-то известно на этапе компиляции. И одни и те же вычисления будут происходить много раз в секунду. Как-то коробит от такой неразумности использования ресурсов... К тому же станет невозможной условная компиляция - сейчас это убого, но получается, хотя и с предупреждением. Тем более когда какая-то константа не определена (и ее обработка в данной модификации не потребуется). Проблема в том, что одна часть компилятора (среды разработки) не умеет считать дробные числа и тем самым запрещает условную компиляцию, а другая часть компилятора - умеет и ругается на условные выражения. Отдает нелепостью и хочется верить что есть нормальное решение для этой ситуации. Изменено 10 апреля, 2022 пользователем natsu Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 9 minutes ago, natsu said: Так ведь не получается с дробными числами! Так не используйте дробные. Или считайте не скажем не в вольтах, а в милливольтах. Это будут целые числа. Или вам нужна точность в микро и нановольтах? ;) 12 minutes ago, natsu said: Проблема в том, что одна часть компилятора (среды разработки) не умеет считать дробные числа Это - НЕ проблема компилятора. Таков стандарт на язык. 14 minutes ago, natsu said: Отдает нелепостью Обрисуйте ваши хотелки более доходчиво, а там глядишь и мифических "нелепостей" станет меньше ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
natsu 0 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба Хотелось бы чтоб одно и то же выражение (тем более не включающее переменных) в разных местах программы считалось одинаково. Это не нормальная "хотелка"? Или желание отключить предупреждение в конкретной строке? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 2 hours ago, natsu said: Хотелось бы чтоб одно и то же выражение (тем более не включающее переменных) в разных местах программы считалось одинаково. Это не нормальная "хотелка"? Это типовая "хотелка" ВСЕХ программистов. Quote Или желание отключить предупреждение в конкретной строке? Вам решать, как обходить грабли в вашем коде. Но по личному опыту - при развитии проекта такие "топорные" методы обхода неприятностей всегда заканчиваются 100% кошмаром программиста. Выше я привел пример как обойти сравнение дробных чисел - записывать все в целых числах, но с разными единицами измерения. Вот на пальцах: #define VOLT_MV (630500) // 630.5V #define VOLT_MV_MAX (VOLT_MV/707) .... #if (VOLT_MV_MAX > (1000 * 1000)) // 1kV .... #endif Если у вас выбран процессор не строго под задачу и есть нормальный запас производительности, и тем более код написан достаточно эффективно, то вариант с const выглядит более разумным. Но тут вам решать. Если пишите на плюсах, то настоятельно рекомендую для данного случая применять constexpr. Но доступен лишь начиная с C++11 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 7 часов назад, natsu сказал: А ведь дальше у меня ветвление в зависимости от логарифма подобной константы, которое правильно было бы сделать на этапе компиляции, но похоже компиляторы еще не достигли такого уровня просветления чтобы считать логарифмы на этапе компиляции.. А вы сами - достигли? Вроде как человек должен быть умнее железки... Цитата Или я ошибаюсь? или я ошибаюсь? Так что же вам самому мешает посчитать его (логарифм) на этапе компиляции? Или школу прогуливали? 5 часов назад, Forger сказал: Все правильно он ругается, т.к. значение volt известно еще на этапе компиляции и проверки условия if в коде не будет. И что? Неужто кейл совсем-совсем не умеет оптимизировать??? Вроде как он должен посчитать это на этапе компиляции и молча удалить недостижимый код (по true). Это обычное поведение нормальных компиляторов. PS: Вангую - предупреждение о недостижимом коде вызывается не этим условием в if, а каким-то кривым кодом по true-ветке, который ТС скрыл. Кейл конечно не IAR, но не думаю, что Кейл настолько туп. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 14 minutes ago, jcxz said: И что? Неужто кейл совсем-совсем не умеет оптимизировать??? Прекрасно умеет! Там компилятор непосредственно от ARM (если v6). Но этот очевидный секрет я сознательно не открывал ТС, так как выше обнаружилась "типовая" фобия: 4 hours ago, natsu said: И одни и те же вычисления будут происходить много раз в секунду. Как-то коробит от такой неразумности использования ресурсов... 14 minutes ago, jcxz said: PS: Вангую - предупреждение о недостижимом коде вызывается не этим условием в if, а каким-то кривым кодом по true-ветке, который ТС скрыл. Нет, тут все верно: if у него "обычный", не препроцессора #if Поэтому результат проверки условия известен еще на этапе компиляции, о чем уверенно и говорит компилятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 1 минуту назад, Forger сказал: Но этот очевидный секрет я сознательно не открывал ТС, так как выше обнаружилась "типовая" фобия: От этой фобии есть хорошее лекарство - ЛИСТИНГИ! Если принимать его регулярно (до обеда быдлокодинга и после). Не менее 3-х раз в день. То это позволит значительно улучшить качество стула программирования. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 10 апреля, 2022 Опубликовано 10 апреля, 2022 · Жалоба 9 часов назад, natsu сказал: как заставить компилятор считать значение. Вы пытаетесь заставить считать препроцессор. У него очень ограниченный набор возможных арифметических действий. И все они над целыми числами. Постчитать выражение с float-операндами он не может. Поэтому он сделает простую текстовую подстановку и передаст это все синтаксическому анализатору и далее, собственно, компилятору. Замена выражения его значением произойдет где-то на этапе оптимизации. И вот тогда, в самом конце, видя никогда не выполняющееся условие (или наоборот, выполняющееся всегда) компилятор выкинет эту проверку, а вам напишет предупреждение об этом. И главное. Файлы .h - это НЕ ФАЙЛЫ ОПРЕДЕЛЕНИЙ! Это файлы объявлений. В них ничего не определяется (т.к. нет выделения памяти), а только объявляется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 18 часов назад, natsu сказал: Вот как с этим бороться? В простых случаях стоит переползать не плюсы и пользоваться constexpr. В примере foo1 гарантировано выберет нужную ветку на этапе компиляции. В foo2 это уже зависит от оптимизации. Препроцессор, как вы уже поняли, с плавучкой вообще не работает. 18 часов назад, natsu сказал: А ведь дальше у меня ветвление в зависимости от логарифма подобной константы А вот тут всё плохо. foo3 будет вычислять log в рантайме, а в foo4 ошибка компиляции. Выбирайте что хуже. К сожалению, это так и на сегодня ничего с этим не сделать. #include <cmath> #define VOLT 630.5f #define VOLT_MAX (VOLT/0.707f) constexpr float volt = 630.5f; constexpr float volt_max = volt/0.707f; void foo1() // Всё хорошо { if constexpr(volt_max > 1000.0f) __NOP(); else __BKPT(0); } void foo2() // Зависит от оптимизации { if (VOLT_MAX > 1000.0f) __NOP(); else __BKPT(0); } void foo3() // Вычисление log во время выполнения { if (log(VOLT_MAX)>10.0f) __NOP(); else __BKPT(0); } void foo4() // Ошибка компиляции { if constexpr (log(volt_max)>10.0f) __NOP(); else __BKPT(0); } 9 часов назад, Darth Vader сказал: И главное. Файлы .h - это НЕ ФАЙЛЫ ОПРЕДЕЛЕНИЙ! Это файлы объявлений. В них ничего не определяется (т.к. нет выделения памяти), а только объявляется. Вообще говоря, это не так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
natsu 0 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба Всем спасибо. Но нормального решения я не нашел - не знаю, можно ли считать нормальным создание в памяти (ПЗУ) const переменной для константы ради того чтобы подавить очевидное (и в данном месте не нужное) предупреждение компилятора. А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения. Но для измерительных приборов есть требования по размещению констант только в ПЗУ. Вот и приходится пользоваться калькулятором, имея компьютер с миллиардами операции в секунду. Да еще и рядом с каждой константой писать #if (это не та константа для которой рассчитал) то #error. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 9 minutes ago, natsu said: А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения. Но для измерительных приборов есть требования по размещению констант только в ПЗУ. Не понимаю ваших жалоб. Храните расчетные константы в ОЗУ, явно у вас не так уж их много. Посчитаете на старте один раз средствами мк, потом в коде применяйте простые сравнения. Вам предложили несколько вариантов. Других средствами препроцессора компилятора пока не придумали. Если и это вам не нравится, то напишите в бюро стандартизации компиляторов, возможно в будущих версиях языка это "исправят" )) 10 minutes ago, natsu said: Вот и приходится пользоваться калькулятором, имея компьютер с миллиардами операции в секунду. В "компьютер с миллиардами операции в секунду" тоже есть калькулятор. В винде так он вообще встроенный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 5 часов назад, VladislavS сказал: А вот тут всё плохо. foo3 будет вычислять log в рантайме, а в foo4 ошибка компиляции. Выбирайте что хуже. К сожалению, это так и на сегодня ничего с этим не сделать. А если немного подумать, то наверняка можно и в compile-time его посчитать. писал уже выше... 33 минуты назад, natsu сказал: А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения. Видимо вы всё-таки прогуливали школу. Иначе бы знали о методах численного вычисления функций (в том числе и логарифмов). И умели бы посчитать во время компиляции. Хоть гуглом воспользуйтесь: поиск по "аппроксимация логарифма". 22 минуты назад, Forger сказал: Не понимаю ваших жалоб. Храните расчетные константы в ОЗУ, явно у вас не так уж их много. Наверняка все константы ТСа можно посчитать во время компиляции. Голову только надо включить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 1 час назад, jcxz сказал: А если немного подумать, то наверняка можно и в compile-time его посчитать. Как-то посчитать, конечно же, можно. Есть даже готовые библиотеки - gcem Но тут только и жди где ногу прострелишь. #include "gcem.hpp" constexpr float volt = 630.5f; constexpr float volt_max = volt/0.707f; void foo5() // Так тоже можно { if constexpr (gcem::log(volt_max)>10.0f) __NOP(); else __BKPT(0); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться