Is it possible to do union type punning in a C constant expression?

Viewed 94

I have a function that converts a series of bytes into a floating point number, using an union. I use it to precisely represent some numbers that are hard to write, such as NaN and Infinity.

float i2f(uint32_t i)
{
    union { uint32_t i; float f; } u;
    u.i = i;
    return u.f;
}

The problem I'm having is that I cannot use this function in places that expect a constant expression, such as static initializers:

// error: initializer element is not constant
float fs[2] = { i2f(0xffc00000), i2f(0x7f800000) };

Is there another way to achieve this same effect, such that the resulting expression is valid as a constant expression?

So far, the only way I found to represent a NaN as a constant is using the __builtin_nan extension, which is not portable. I would prefer something that works inside the boundaries of the C standard, if possible.

1 Answers

The C standard does not provide any features in strictly conforming code that would yield an integer constant expression for this.

The closest we could come might be creating a compound literal and taking a member of it:

(union { uint32_t u; float f; }) { 0xffc00000} .f

However, this is not a constant expression as the C standard defines it except C 2018 6.6 10 says “An implementation may accept other forms of constant expressions.”

What may serve your purpose is simply to define unions containing the desired values:

union { uint32_t u; float f; } fs[2] = { { 0xffc00000} , { 0x7f800000 } };

after which you would use their members, fs[0].f, fs[1].f, and so on.

Related