是否可以在 C 常量表达式中进行联合类型双关?
Is it possible to do union type punning in a C constant expression?
我有一个函数可以使用联合将一系列字节转换为浮点数。我用它来精确表示一些难写的数字,比如NaN和Infinity。
float i2f(uint32_t i)
{
union { uint32_t i; float f; } u;
u.i = i;
return u.f;
}
我遇到的问题是我无法在需要常量表达式的地方使用此函数,例如静态初始化程序:
// error: initializer element is not constant
float fs[2] = { i2f(0xffc00000), i2f(0x7f800000) };
是否有另一种方法可以实现同样的效果,使得生成的表达式作为常量表达式有效?
到目前为止,我发现将 NaN 表示为常量的唯一方法是使用不可移植的 __builtin_nan 扩展。如果可能的话,我更喜欢在 C 标准范围内工作的东西。
C 标准在严格符合的代码中没有提供任何可以为此产生 整数常量表达式 的特性。
我们最接近的可能是创建一个复合文字并获取其中的一个成员:
(union { uint32_t u; float f; }) { 0xffc00000} .f
但是,这不是 C 标准定义的常量表达式,除了 C 2018 6.6 10 说“实现可以接受其他形式的常量表达式。”
可以满足您的目的的是简单地定义包含所需值的联合:
union { uint32_t u; float f; } fs[2] = { { 0xffc00000} , { 0x7f800000 } };
之后您将使用他们的成员,fs[0].f
、fs[1].f
,等等。
我有一个函数可以使用联合将一系列字节转换为浮点数。我用它来精确表示一些难写的数字,比如NaN和Infinity。
float i2f(uint32_t i)
{
union { uint32_t i; float f; } u;
u.i = i;
return u.f;
}
我遇到的问题是我无法在需要常量表达式的地方使用此函数,例如静态初始化程序:
// error: initializer element is not constant
float fs[2] = { i2f(0xffc00000), i2f(0x7f800000) };
是否有另一种方法可以实现同样的效果,使得生成的表达式作为常量表达式有效?
到目前为止,我发现将 NaN 表示为常量的唯一方法是使用不可移植的 __builtin_nan 扩展。如果可能的话,我更喜欢在 C 标准范围内工作的东西。
C 标准在严格符合的代码中没有提供任何可以为此产生 整数常量表达式 的特性。
我们最接近的可能是创建一个复合文字并获取其中的一个成员:
(union { uint32_t u; float f; }) { 0xffc00000} .f
但是,这不是 C 标准定义的常量表达式,除了 C 2018 6.6 10 说“实现可以接受其他形式的常量表达式。”
可以满足您的目的的是简单地定义包含所需值的联合:
union { uint32_t u; float f; } fs[2] = { { 0xffc00000} , { 0x7f800000 } };
之后您将使用他们的成员,fs[0].f
、fs[1].f
,等等。