ViKo 1 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба inline uint8_t HMCAD_Cgain_dB(uint8_t dB) { return (dB <= 12) ? dB : 0; } Test = HMCAD_Cgain_dB(11); спокойно заносит в Test число 11, не производя никаких run-time вычислений. Хватило же интеллекта понять. Нет, при уровне оптимизации 0 вызывает некую функцию вот такого имени _ZN12hmcad1511_ns14HMCAD_Cgain_dBEh. Но не в этом суть. 25 минут назад, Forger сказал: Где именно? Покажите код. Какой код? Нет никакого кода (не компилируется же). А для показанной здесь функции: ;;;96 Test = HMCAD_Cgain_dB(11); 0000f0 6001 STR r1,[r0,#0] ; Test 0000f2 2100 MOVS r1,#0 ;;;97 Test = HMCAD_Cgain_dB(13); 0000f4 6001 STR r1,[r0,#0] ; Test Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба inline - это по сути обычная runtime функция, поэтому внутри нее не прокатит никакой static_assert. Причем абсолютно до лампочки, если значения известны на этапе компиляции. Замените inline на constexpr и тогда компилятор перестанет ругаться на static_assert Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба 3 минуты назад, Forger сказал: Замените inline на constexpr и тогда компилятор перестанет ругаться на static_assert Ничего не меняется. Да и не может измениться, AHTOXA разъяснил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба 11 minutes ago, ViKo said: Ничего не меняется. Да и не может измениться, AHTOXA разъяснил. Посмотрите пример от AHTOXA еще раз внимательнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба 2 минуты назад, Forger сказал: Походу вы все еще не поняли разницу между про compile-time и runtime выражениями. Заканчивайте фантазировать и импровизировать. Мне нужны советы, а не оценки моих умений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба 15 minutes ago, ViKo said: Мне нужны советы, уже все прозвучало: 1 hour ago, AHTOXA said: присвоить результат выполнения constexpr-функции constexpr-переменной и проверить значение этой переменной. 1 hour ago, Forger said: Хотите делать проверку входных параметров некой функции (не макроса), то делайте это руками Повторюсь: найдите реализацию static_assert и все станет сразу понятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 17 часов назад, Forger сказал: Убираю const - ругается линкер как и должен. Не понимаю. Пора читать мануалы и мне 17 часов назад, Forger сказал: Для данной ситуации нет никакой разницы между C и C++. Вы используете примитивные вещи из голого С. Конечно они будут работать в С++. По поводу const есть принципиальная разница между С и С++. const объекты в С - это обычные объекты с внешним связыванием (external linkage) по умолчанию. А в С++ const объекты по умолчанию имеют внутреннее связывание (internal linkage). Сишное поведение можно привести к плюсовому, указав явно static, а плюсовое к сишному, указав extern. Такое отличие в С++ было введено специально, чтобы можно было свести к минимуму использование макросов для задания литералов/"констант". Т.е. если в плюсовом файле объявить константный объект, и в коде нигде нет операции взятия адреса этого объекта, то компилятор имеет право (и именно так и делают все вменяемые компиляторы) не инстанцировать объект вообще, а просто использовать его значение - внутреннее связывание гарантирует, что за пределами данной единицы компиляции на этот объект тоже никто не может сослаться, поэтому проблем с линковой тоже нет. Поэтому объявлять константные объекты в заголовках в С++ не только можно, но и является рекомендуемой практикой - накладных нет, управляемость кода на высоком уровне (нет рассинхронизации по константам) в разных единицах компиляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 18 hours ago, Forger said: Вставьте ваш h-файл (где объявлена const без extern) как минимум в два разных исходника (неважно С или С++) и сделайте сборку проекта (линковку), не компиляцию, а сборку. Посмотрите что скажет линкер. В линкере кейла существует какой-то странный костыль - подобный код собирается нормально. Какой магией он "схлопывает" два объекта в один, я не знаю. Была как-то тема "написал код в кейле, переношу в гцц, памагите, неработает!!", сам я вопрос не исследовал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 4 minutes ago, esaulenka said: В линкере кейла существует какой-то странный костыль - подобный код собирается нормально. Какой магией он "схлопывает" два объекта в один, я не знаю. Была как-то тема "написал код в кейле, переношу в гцц, памагите, неработает!!", сам я вопрос не исследовал. Да keil тут ни при чем, причину коллега выше постом все отлично расписал. Но попробуйте убрать квалификатор const хотя бы у одного объекта в h-файле и получите закономерные ошибки линковки (на всякий случай проверил в arm compiler v6). Стараюсь где возможно вместо const использовать constexpr. Сокращаю зону видимости каждого из constexpr настолько, насколько это допустимо. Классические #define у меня остались только в одном файле (GlobalSetting.h), но причина проста - у Keil есть очень удобный Configuration wizard, который умеет парсить только h-файлы, увы, лишь на базе #define :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 12 часов назад, AHTOXA сказал: Так что компилятор ругается правильно. Вы можете проверить результат вызова функции, присвоив его constexpr-переменной: static constexpr uint8_t gain = HMCAD_Cgain_dB(11); static_assert(gain <= 12, "Gain in dB is too large"); Хорошо, так работает. А как бы запихнуть это в одно целое? В виде макро можно. А в виде функции - никак? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 5 minutes ago, Forger said: Да keil тут ни при чем Стряхнул пыль с MDK 5.14 (другого нет, да и этот несколько лет не запускал). Ругается, как и положено. Действительно, нельзя верить всему, что пишут в интернетах :-( Извините. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 13 minutes ago, ViKo said: Хорошо, так работает. А как бы запихнуть это в одно целое? В виде макро можно. А в виде функции - никак? Тут как в известной поговорке - "и рыбку съесть и на ... сесть" Используйте вместо static_assert что-то другое, которое умеет работать в runtime. Например, сыпет сообщения в консоль или файл. Рекомендую RTT от segger, просто и не требует доп. портов, кроме SWD канала для отладчика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 17 июля, 2019 Опубликовано 17 июля, 2019 · Жалоба 36 минут назад, ViKo сказал: Хорошо, так работает. А как бы запихнуть это в одно целое? В виде макро можно. А в виде функции - никак? Можно использовать шаблонную функцию: template <uint8_t i> uint8_t HMCAD_Cgain_dB() { static_assert(i<12, "gain too big!"); return i; } Применять так: uint8_t gain = HMCAD_Cgain_dB<11>(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба То есть, явно создали экземпляр шаблонной функции, но вместо типа используем константу? Кто автор сей чудесной конструкции? В учебниках не нашел, и сам бы никогда не догадался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба Да, это называется не-типовой параметр шаблона. Я же правильно понимаю, что у вас эта функция вызывается один раз в программе, с константным параметром? И вы хотите проверить то, что параметр находится в заданных пределах во время компиляции? Тогда эта функция подходит. Или можно сделать шаблонную структуру с константным членом: template <unsigned busFreq> struct FreqCalculator { static_assert(busFreq < 400, "Bus freq too high"); static constexpr unsigned ahbFreq { busFreq }; static constexpr unsigned apb1Freq { busFreq / 2 }; static constexpr unsigned apb2Freq { busFreq }; } И потом, где-то в общем заголовочном файле: using CpuFreq = FreqCalculator<200>; и использовать в любом месте: auto freq = CpuFreq::apb1Freq; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться