Alexey_N 0 14 июня, 2019 Опубликовано 14 июня, 2019 · Жалоба Вот, в одном проекте, в начале main.c стоят строчки: #define FCLK 16.0E6 // 16MHz #define FREQ_COEFF (double)(pow(2.0,32) / FCLK) Подразумевается, что в препроцессоре вычислится FREQ_COEFF (получается где-то 268.4), после чего это число будет использоваться в теле программы. И именно так и происходит. А в другом, совершенно аналогичном проекте, функция pow() в препроцессоре не вычисляется, а начинает тормозить во всех тех местах, где упоминается FREQ_COEFF. Как это? Почему так происходит? Как отследить/настроить/победить? Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 14 июня, 2019 Опубликовано 14 июня, 2019 · Жалоба Препроцессор ничего вычислять не умеет, он только текст подставляет, и если компилятор умный, то догадается что FREQ_COEFF константа и посчитает её при компиляции, если не очень или уровень оптимизации невысокий, скомпилирует как попросили вызов pow. #define FREQ_COEFF (4294967296.0/FCLK) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 14 июня, 2019 Опубликовано 14 июня, 2019 · Жалоба 14 minutes ago, _pv said: Препроцессор ничего вычислять не умеет, он только текст подставляет, и если компилятор умный, то догадается что FREQ_COEFF константа и посчитает её при компиляции, если не очень или уровень оптимизации невысокий, скомпилирует как попросили вызов pow. Всё, разобрался! Ключевое слово = УРОВЕНЬ ОПТИМИЗАЦИИ!!! При низких уровнях препроцессор - глупый, а при максимальных - всё получается. Огромное мерси!:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 14 июня, 2019 Опубликовано 14 июня, 2019 · Жалоба Чтобы не надеяться, что компилятор сам поймёт, что выражение есть константа времени компиляции, и вычислит её один раз, надо самому объявить её таковой с помощью квалификатора constexpr. От компилятора понадобится поддержка стандарта с++11. constexpr double FCLK=16.0; // 16 MHz constexpr double FREQ_COEFF=pow(2.0,32)/FCLK; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 14 hours ago, Alexey_N said: Всё, разобрался! Ключевое слово = УРОВЕНЬ ОПТИМИЗАЦИИ!!! При низких уровнях препроцессор - глупый, а при максимальных - всё получается. препроцессор глупый всегда. даже без C++11 вместо дефайна можно объявить const double FREQ_COEFF=pow(2.0,32)/FCLK; тогда в худшем случае посчитает один раз, если не догадается вычислить на этапе компиляции. но как и в случае с constexpr в заголовочный файл для включения в другие части тогда придётся написать extren const double FREQ_COEFF; а вычислить где-то один раз отдельно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 17 часов назад, Alexey_N сказал: Ключевое слово = УРОВЕНЬ ОПТИМИЗАЦИИ!!! При низких уровнях препроцессор - глупый, а при максимальных - всё получается. Никаких глупых/умных препроцессоров не бывает. Глупыми могут только неумехи, не понимающие как работает их инструмент. Препроцессор всегда выполняет только текстовую подстановку. Вам уже это сказали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 3 hours ago, jcxz said: Никаких глупых/умных препроцессоров не бывает. Глупыми могут только неумехи, не понимающие как работает их инструмент. Препроцессор всегда выполняет только текстовую подстановку. Вам уже это сказали. Да, я прошу прощения, в суете неправильно выразился. Разумеется речь шла о компиляторе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 17 hours ago, Darth Vader said: Чтобы не надеяться, что компилятор сам поймёт, что выражение есть константа времени компиляции, и вычислит её один раз, надо самому объявить её таковой с помощью квалификатора constexpr. От компилятора понадобится поддержка стандарта с++11. Увы, не поддерживает :(. (Ругается, хотя и знает это слово.) Может быть эту поддержку где-то в настройках включать надо? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 5 hours ago, _pv said: даже без C++11 вместо дефайна можно объявить const double FREQ_COEFF=pow(2.0,32)/FCLK; тогда в худшем случае посчитает один раз, если не догадается вычислить на этапе компиляции. Так очень было бы хорошо, но вот при компиляции ругается: Error[Pe059]: function call is not allowed in a constant expression Что я сделал не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба Дословный перевод: вызов функций не поддерживается в константных выражениях. Значит не судьба через constexpr. В таких выражениях имеются некоторые ограничения, зависящие от версии поддерживаемого стандарта С++:11/14/17 и особенностей компилятора. Чем новее стандарт и "продвинутей" компилятор, тем меньше в нём ограничений на средства вычисления константных выражений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 56 минут назад, Alexey_N сказал: Error[Pe059]: function call is not allowed in a constant expression Что я сделал не так? Вам же компилятор английским по белому сказал: вызываете функцию. Избавьтесь от pow() и никакие c++11 не потребуются. PS: Видел уже как некоторые "программисты" передают числовые аргументы в функцию переводя их в строку (а внутри - переводя обратно в число). Возведение 2 в целую степень при помощи функции pow() - этот "перл" быдлокодерства будет не хуже. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 3 minutes ago, jcxz said: Вам же компилятор английским по белому сказал: вызываете функцию. Избавьтесь от pow() и никакие c++11 не потребуются. Это очевидно, но вот совсем избавляться от функций в предварительных расчетах как-то не охота... Видимо должен существовать некий легальный механизм, чтобы заранее посчитать все константы в начале игры, вне зависимости от с++11. Ну, по крайней мере, хотелось бы на это надеяться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 56 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба То есть использовать #define FREQ_COEFF (4294967296 / FCLK) #define FREQ_COEFF ((1 << 32) / FCLK) нельзя ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexey_N 0 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 46 minutes ago, x893 said: То есть использовать #define FREQ_COEFF (4294967296 / FCLK) #define FREQ_COEFF ((1 << 32) / FCLK) нельзя ? Да с калькулятором в руках можно вообще порешать большинство жизненных затруднений! :) Конечно, в данном простейшем примере всё так и делается. Но ведь хотелось бы решить проблему в общем случае, чтобы потом уже не возвращаться к этим непоняткам, когда вначале проекта рассчитываются константы не такие простые, да и по сложному набору функций... Ну раз уж разговор зашел предметный, то почему бы и не дорыхлить тему до конца? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 56 15 июня, 2019 Опубликовано 15 июня, 2019 · Жалоба 10 minutes ago, Alexey_N said: то почему бы и не дорыхлить тему до конца? то почему бы не взрыхлить тему до конца Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться