Jump to content
    

как избавиться от предупреждений компилятора

Добрый день,

Столкнулся с ситуацией, когда компилятор отказывается считать константу на этапе компиляции, но зато злобно выдает предупреждение о ее значении. Подскажите, плиз, как избавиться от предупреждения в этом конкретном месте либо как заставить компилятор считать значение.

Имеется файл определений .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]

 

Вот как с этим бороться? 
А ведь дальше у меня ветвление в зависимости от логарифма подобной константы, которое правильно было бы сделать  на этапе компиляции, но похоже компиляторы еще не достигли такого уровня просветления чтобы считать логарифмы на этапе компиляции.. Или я ошибаюсь?

 

Share this post


Link to post
Share on other sites

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) ....

 

Share this post


Link to post
Share on other sites

1 час назад, Forger сказал:

Если уж начали применять препроцессор (#define), то применяйте его и для условий: #if

Так ведь не получается с дробными числами!

 

Использование const заставит вынести константы (!) из заголовка в отдельный файл и вместо использования константы будет обращение к ячейке памяти, значение которой вообще-то известно на этапе компиляции. И одни и те же вычисления будут происходить много раз в секунду. Как-то коробит от такой неразумности использования ресурсов... К тому же станет невозможной условная компиляция - сейчас это убого, но получается, хотя и с предупреждением. Тем более когда какая-то константа не определена (и ее обработка в данной модификации не потребуется). 

 

Проблема в том, что одна часть компилятора (среды разработки) не умеет считать дробные числа и тем самым запрещает условную компиляцию, а другая часть компилятора - умеет и ругается на условные выражения. Отдает нелепостью и  хочется верить что есть нормальное решение для этой ситуации.

Edited by natsu

Share this post


Link to post
Share on other sites

9 minutes ago, natsu said:

Так ведь не получается с дробными числами!

Так не используйте дробные. Или считайте не скажем не в вольтах, а в милливольтах. Это будут целые числа. Или вам нужна точность в микро и нановольтах? ;)

12 minutes ago, natsu said:

Проблема в том, что одна часть компилятора (среды разработки) не умеет считать дробные числа

Это - НЕ проблема компилятора. Таков стандарт на язык.

 

14 minutes ago, natsu said:

Отдает нелепостью

Обрисуйте ваши хотелки более доходчиво, а там глядишь и мифических "нелепостей" станет меньше ;)

Share this post


Link to post
Share on other sites

Хотелось бы чтоб одно и то же выражение (тем более не включающее переменных) в разных местах программы считалось одинаково. Это не нормальная "хотелка"? Или желание отключить предупреждение в конкретной строке?

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

7 часов назад, natsu сказал:

А ведь дальше у меня ветвление в зависимости от логарифма подобной константы, которое правильно было бы сделать  на этапе компиляции, но похоже компиляторы еще не достигли такого уровня просветления чтобы считать логарифмы на этапе компиляции..

А вы сами - достигли?  :wink:

Вроде как человек должен быть умнее железки...

Цитата

Или я ошибаюсь?

или я ошибаюсь?  :wink:

Так что же вам самому мешает посчитать его (логарифм) на этапе компиляции? Или школу прогуливали?  :biggrin:

 

5 часов назад, Forger сказал:

Все правильно он ругается, т.к. значение volt известно еще на этапе компиляции и проверки условия if в коде не будет.

И что? Неужто кейл совсем-совсем не умеет оптимизировать??? :shok:

Вроде как он должен посчитать это на этапе компиляции и молча удалить недостижимый код (по true). Это обычное поведение нормальных компиляторов.

 

PS: Вангую - предупреждение о недостижимом коде вызывается не этим условием в if, а каким-то кривым кодом по true-ветке, который ТС скрыл.

Кейл конечно не IAR, но не думаю, что Кейл настолько туп.  :wink:

Share this post


Link to post
Share on other sites

14 minutes ago, jcxz said:

И что? Неужто кейл совсем-совсем не умеет оптимизировать??? :shok:

Прекрасно умеет! Там компилятор непосредственно от ARM (если v6).

Но этот очевидный секрет я сознательно не открывал ТС, так как выше обнаружилась "типовая" фобия:

4 hours ago, natsu said:

И одни и те же вычисления будут происходить много раз в секунду. Как-то коробит от такой неразумности использования ресурсов...

 

14 minutes ago, jcxz said:

PS: Вангую - предупреждение о недостижимом коде вызывается не этим условием в if, а каким-то кривым кодом по true-ветке, который ТС скрыл.

Нет, тут все верно: if у него "обычный", не препроцессора #if 

Поэтому результат проверки условия известен еще на этапе компиляции, о чем уверенно и говорит компилятор.

Share this post


Link to post
Share on other sites

1 минуту назад, Forger сказал:

Но этот очевидный секрет я сознательно не открывал ТС, так как выше обнаружилась "типовая" фобия:

От этой фобии есть хорошее лекарство - ЛИСТИНГИ!  :good:

Если принимать его регулярно (до обеда быдлокодинга и после). Не менее 3-х раз в день. :wink:  То это позволит значительно улучшить качество стула программирования.

Share this post


Link to post
Share on other sites

9 часов назад, natsu сказал:

как заставить компилятор считать значение.

Вы пытаетесь заставить считать препроцессор. У него очень ограниченный набор возможных арифметических действий. И все они над целыми числами. Постчитать выражение с float-операндами он не может. Поэтому он сделает простую текстовую подстановку и передаст это все синтаксическому анализатору и далее, собственно, компилятору. Замена выражения его значением произойдет где-то на этапе оптимизации. И вот тогда, в самом конце, видя никогда не выполняющееся условие (или наоборот, выполняющееся всегда) компилятор выкинет эту проверку, а вам напишет предупреждение об этом.

И главное. Файлы .h - это НЕ ФАЙЛЫ ОПРЕДЕЛЕНИЙ!

Это файлы объявлений. В них ничего не определяется (т.к. нет выделения памяти), а только объявляется.

Share this post


Link to post
Share on other sites

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 - это НЕ ФАЙЛЫ ОПРЕДЕЛЕНИЙ!

Это файлы объявлений. В них ничего не определяется (т.к. нет выделения памяти), а только объявляется.

Вообще говоря, это не так.

Share this post


Link to post
Share on other sites

Всем спасибо.

Но нормального решения я не нашел - не знаю, можно ли считать нормальным создание в памяти (ПЗУ) const переменной для константы ради того чтобы подавить очевидное (и в данном месте не нужное) предупреждение компилятора.

 

А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения. Но для измерительных приборов есть требования по размещению констант только в ПЗУ. Вот и приходится пользоваться калькулятором, имея компьютер с миллиардами операции в секунду. Да еще и рядом с каждой константой писать #if (это не та константа для которой рассчитал) то #error.

Share this post


Link to post
Share on other sites

9 minutes ago, natsu said:

А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения. Но для измерительных приборов есть требования по размещению констант только в ПЗУ. 

Не понимаю ваших жалоб. Храните расчетные константы в ОЗУ, явно у вас не так уж их много.

Посчитаете на старте один раз средствами мк, потом в коде применяйте простые сравнения.

Вам предложили несколько вариантов. Других средствами препроцессора компилятора пока не придумали.

Если и это вам не нравится, то напишите в бюро стандартизации компиляторов, возможно в будущих версиях языка это "исправят" ))

 

10 minutes ago, natsu said:

Вот и приходится пользоваться калькулятором, имея компьютер с миллиардами операции в секунду.

В "компьютер с миллиардами операции в секунду" тоже есть калькулятор. В винде так он вообще встроенный.

Share this post


Link to post
Share on other sites

5 часов назад, VladislavS сказал:

А вот тут всё плохо. foo3 будет вычислять log в рантайме, а в foo4 ошибка компиляции. Выбирайте что хуже. К сожалению, это так и на сегодня ничего с этим не сделать.

А если немного подумать, то наверняка можно и в compile-time его посчитать. :wink:   писал уже выше...

33 минуты назад, natsu сказал:

А расчетные константы, например логарифм константы - вообще никак, только считать во время выполнения.

Видимо вы всё-таки прогуливали школу.  :unknw: Иначе бы знали о методах численного вычисления функций (в том числе и логарифмов). И умели бы посчитать во время компиляции.

Хоть гуглом воспользуйтесь: поиск по "аппроксимация логарифма".

22 минуты назад, Forger сказал:

Не понимаю ваших жалоб. Храните расчетные константы в ОЗУ, явно у вас не так уж их много.

Наверняка все константы ТСа можно посчитать во время компиляции. Голову только надо включить.

Share this post


Link to post
Share on other sites

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);
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...