Jump to content

    

C++, extern "C" и namespace

В c++ переменные, объявленные const, по умолчанию имеют внутреннее связывание. Поэтому в том случае, когда вы объявляете const int x = 3; в *.h файле, то можете смело включать его в любое количество  cpp файлов. Это будет примерно аналогично тому, если бы вы в каждом из cpp файлов объявили свою статическую переменную.

В си не так.

 

Share this post


Link to post
Share on other sites

Спасибо, "понел"!  

А вот еще загадка:

inline constexpr uint8_t HMCAD_Cgain_dB(uint8_t dB)
{
    static_assert(dB <= 12, "Gain in dB is too large");
    return dB;
}

 

Test = HMCAD_Cgain_dB(11);

...: error:  #28: expression must have a constant value
        static_assert(dB <= 12, "Gain in dB is too large");

Share this post


Link to post
Share on other sites

Если не требуется статическое размещение, можно уложить константы в отдельный enum, плюсы: не использует магию препроцессора, учитывает неймспейсы, невозможно размазать константы по всему файлу - они всегда в одном месте, можно положить внутрь класса - явно показав где константа используется.

Share this post


Link to post
Share on other sites
1 час назад, ViKo сказал:

А вот еще загадка:

inline constexpr uint8_t HMCAD_Cgain_dB(uint8_t dB)
{
    static_assert(dB <= 12, "Gain in dB is too large");
    return dB;
}



 

Test = HMCAD_Cgain_dB(11);

...: error:  #28: expression must have a constant value
        static_assert(dB <= 12, "Gain in dB is too large");

Дело в том, что constexpr-функция может вызываться и во время выполнения, как обычная функция. То есть, вполне допустим вызов

auto i = getUserInput();
HMCAD_Cgain_dB(i);

Так что компилятор ругается правильно. Вы можете проверить результат вызова функции, присвоив его constexpr-переменной:

static constexpr uint8_t gain = HMCAD_Cgain_dB(11);

static_assert(gain <= 12, "Gain in dB is too large");


 


 

Share this post


Link to post
Share on other sites

На функцию

inline uint8_t HMCAD_Cgain_dB(uint8_t dB)
{
    static_assert(dB <= 12, "Gain in dB is too large");
    return dB;
}

ругается точно так же: expression must have a constant value. Дело не в constexpr или const.

Share this post


Link to post
Share on other sites
7 minutes ago, ViKo said:

к же: expression must have a constant value. Дело не в constexpr или const.

Правильно он ругается: constexpr имеет сходный функционал, как и #define (если грубо), но имеет гораздо больше возможностей.

constexpr по сути точно также как и #define парсится еще в препроцессоре, до вызова компилятора, НЕ runtime.

Если на этапе компиляции нельзя посчитать значения внутри constexpr -функции, то будет вполне логичная ошибка.

 

 

Share this post


Link to post
Share on other sites
6 минут назад, ViKo сказал:

На функцию

inline uint8_t HMCAD_Cgain_dB(uint8_t dB)
{
    static_assert(dB <= 12, "Gain in dB is too large");
    return dB;
}

ругается точно так же: expression must have a constant value. Дело не в constexpr или const.

Вы ещё раз перечитайте мой ответ:)
 

Share this post


Link to post
Share on other sites

Сейчас там никаким constexpr не пахнет. Проблема в inline и static_assert.

2 минуты назад, AHTOXA сказал:

Вы ещё раз перечитайте мой ответ

Ваше разъяснение понятно, однако, у меня в функцию передается константа.

Решение же не видится мне красивым и логичным. Проще просто забить на проверку.

Share this post


Link to post
Share on other sites
3 minutes ago, ViKo said:

Сейчас там никаким constexpr не пахнет.

И то верно ))

 

Quote

Проблема в inline и static_assert.

inline тут ни при чем, откройте реализацию static_assert, все станет понятно.

Share this post


Link to post
Share on other sites

Немного разовью.

static_assert - это проверка времени компиляции. Поэтому проверять оно может только значения, вычисляемые во время компиляции.

Переменная constexpr - гарантированно вычисляется во время компиляции. Поэтому такая конструкция будет работать всегда:

constexpr int bufferSize = sizeof(SomeStruct)/sizeof(int);
static_assert(bufferSize < 20);

Вы же пытаетесь вставить static_assert в функцию. Даже если эта функция constexpr, она может быть вызвана во время выполнения программы, поэтому внутри функции проверка её параметра при помощи static_assert() не срабатывает.

Выход - присвоить результат выполнения constexpr-функции constexpr-переменной и проверить значение этой переменной.
 

Share this post


Link to post
Share on other sites
2 минуты назад, Forger сказал:

inline тут ни при чем

Да, не при чем. 

Share this post


Link to post
Share on other sites

Вот в макрофункции с помощью static_assert я могу устроить требуемую проверку, а в функциях, значит, нет.

#define DWT_DELAY_RESTART(Time);        \
    static_assert((Time * SYSCLK + 999999999uLL) / 1000000000uLL < 1uLL << 32, "Over Delay");    \
    cst = DWT->CYCCNT; 

Share this post


Link to post
Share on other sites
7 minutes ago, ViKo said:

Вот в макрофункции с помощью static_assert я могу устроить требуемую проверку, а в функциях, значит, нет.

Это абсолютно логично и очевидно: "макрофункции" вычисляются еще на этапе компиляции, точнее на этапе работы препроцессора (compile-time), а обычные функции - в процессе работы кода (runtime).

Хотите делать проверку входных параметров некой функции (не макроса), то делайте это руками - через банальный "if".

Share this post


Link to post
Share on other sites

Зато не логично, что на этапе компиляции в inline функцию передается константа 11, а static_assert отказывается сравнивать ее с 12. :biggrin:

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

делайте это руками - через банальный "if"

в соседней функции делаю через ? :

Share this post


Link to post
Share on other sites
8 minutes ago, ViKo said:

Зато не логично, что на этапе компиляции в функцию передается константа 11, а static_assert отказывается сравнивать ее с 12. :biggrin:

Такое возможно лишь с constexpr функцией или макросом на базе define.

В обычной функции такое не прокатит. Обычная функция - это набор команд, кода внутри МК. Обычная функция (inline в т. ч.) понятия не имеет, что именно придет ей на вход и потому применить внутри такой функции static_assert в принципе невозможно. О чем однозначно говорит компилятор.

 

 

8 minutes ago, ViKo said:

на этапе компиляции в inline функцию передается константа 11

Где именно? Покажите код.

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now