Question

I have to write some functions with a significant amount of constant in it in a relatively small amount of lines.

( Don't bother about the way I wrote the formula, it's there to simply express the fact that I have a lot of constants in a small package, this specific example is small too, in practice I have a minimum of 6-7 constants for each function )

T foo( T x )
{
  return k1 * k2 * x - k3;
}

Assuming that I'm not interested in declaring the constants as static ( it will also cause problems with the naming convention in my specific case ) const T k1 = 42; , I would like to find an alternative .

A viable alternative can be

T foo( T x )
{
  return uint32_t{42} * uint32_t{21} * x - uint32_t{33};
}

At this point there are 2 main problems:

  • I'm not sure if this kind of declaration will create an entire object or just "a number"
  • it's a C++ only solution and I'm writing really simple functions that should be C99+ compatible .

Why I would like to do this ?

It's simple, the values for this constants are highly variable, really small values or big values, with really small values there is a significant amount of space wasted, plus this constants are math constants so they will never change and I can optimize this section right from the first release.

There is also another aspect, the default type for numeric constants is a signed integer, I would like to go for an unsigned integer type of arbitrary size.

The problem with the static declaration const T k1 = 42; outside the functions, is that different constants have the same name, the value of the constant is different because the function is different, but the name of the constant, mathematically speaking, is the same, so with this solution I'll end up having multiple declarations of the same variable in the same scope. That's why I can't use names or this kind of declarations .

Do you have any idea for writing this in a way that is compatible with both C++ and C ?

Was it helpful?

Solution

In C, for integers, you add 'U', 'L', or 'LL' to numbers to make them unsigned, long, or long long in a few combinations

a = -1LL;  // long long
b = -1U;   // unsigned
c = -1ULL; // unsigned long long
d = -1LLU; // unsigned long long
e = -1LU;  // unsigned long
f = -1UL;  // unsigned long

One other option, in C, is to cast. The compiler, very probably, will do the right thing :)

return (uint32)42 - (int64)10;

But probably the best option, as pointed by ouah in the comments below, is to use Macros for integer constants (C99 Standard 7.18.4)

a = UINT32_C(-1); // -1 of type uint_least32_t
b = INT64_C(42);  // 42 of type int_least64_t

OTHER TIPS

Is there something wrong this?

inline T foo(T x)
{
    int k1 = 42;
    int k2 = 21;
    int k3 = 33;

    return 1ull * x * k1 * k2 - k3;
}

Your comments on the other answer suggest you are unsure about which types to use for the constants. I don't see what the problem is with just using any type in which that constant is representable.

For the calculation expression, you would need to think about the size and signed-ness of intermediate calculations. In this example I start with 1ull to use unsigned arithmetic mod 2^64. If you actually wanted arithmetic mod 2^32 then use 1ul instead, and so on.

Can you elaborate on what you meant by "space wasted"? It sounds as if you think there is some problem with using 64-bit ints. What sort of "space" are you talking about?

Also, to clarify, the reason you don't want to declare k1 global is because k1 has a different value in one function than it does in another function? (As opposed to it having the same value but you think it should have a different data type for some reason).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top