Search code examples
cc++11constantsansi-c

ANSI-C constant-expression function like C++ constexpr?


Putting it simple, is there an ANSI-C way of making a function a constant expression?

  1. Pure ANSI-C but GNU extensions are acceptable - NO C++, though.
  2. Preferably without relying on macros.
  3. Something that surely behaives like the C++ constexpr and won't be solved at run time.

Background:

I need to implement a lot of math in an embedded processor that does not have floating point, so I am using fixed point in my application.

I don't like to see cryptic constants in my header files, though. My hardware needs several floating-point constants (e.g. 130.7 microseconds, 0.2503 mJ) and I'd really like to be able to read (and change) my constants as the parts datasheet values are listed.

At a given moment, my hardware needs to use this constants, for example, to fill in a timer reload value, and, since the values are constant, i'd like to have somthing like:

// Header file.
static const int values_table[] =
{
    _Time( 123.45 ),    // 123.45 microseconds.
    // ...
};

And then:

// Application source file.

int conv_to_timer( x ) { /* my calculations - all const. */ }

// ...

void my_code( void )
{
    // ...
    timer_reload = conv_to_timer( values_table[ index ] );

One approach would be making my _Time( x ) macro to do all calculations needed for the timer values but it is not flexible (i.e. not comparable against someting outside) neither portable (a different hardware would demand a different calculation).

Any suggestions for an elegant approach, please?


Solution

  • TL;DR: use macros.

    Standard C does not have a direct analog of C++'s constexpr. The closest things are macros and inline functions, and of those two, macros can be used in some ways that inline functions cannot be used -- in particular, inline functions cannot be used where C requires a constant expression (hmmm ... sounds similar to any C++ keyword you know?), but macros, on the other hand, can expand to suitable expressions.

    constexpr was introduced into C++ largely to provide an alternative to macros where a non-trivial but compile-time-computable expression is required. I believe they also have some advantages, such as with respect to the types of values that they can cause to be computed at compile time, but those seem not relevant to your particular case. In C, where constexpr was never introduced, macros are still the standard way to go.

    Your primary objection to using macros seems to be essentially about code style. You observe that the body of a C++ constexpr function can be in a different translation unit than the "calls" to it, and that is apparently attractive to you. Do note, however, that if that were an option for you then you would still need at least declarations of such functions in the translation units that used them, so you'd not actually saving very much in terms of cleanliness. Furthermore, although each translation unit must contain the body of each macro it uses, you can still segregate the macro definitions into a separate header.

    Overall, then, I don't see that avoiding macros -- if you could -- would really gain you anything. I'm inclined to think that the C++ community's general aversion to macros was as big a motivation for constexpr as any functional benefit. If it happens that you are afflicted by that particular aversion then you really need to get over it to program effectively in standard C.