Перейти к содержанию
    

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

Добрый день,

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

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

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

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

 

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

Изменено пользователем natsu

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, natsu said:

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

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

12 minutes ago, natsu said:

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

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

 

14 minutes ago, natsu said:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Цитата

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

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

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

 

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

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

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

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, jcxz said:

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

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

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

4 hours ago, natsu said:

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

 

14 minutes ago, jcxz said:

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, natsu said:

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

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

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

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

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

 

10 minutes ago, natsu said:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...