17
\$\begingroup\$

I have been trying to learn some deeper aspects of UE4 and while reading many examples codes and also the source base of the engine, I noticed that sometimes people (and the very source code) use the standard C++ float primitive, but sometimes use UE4's custom implementation FFloat32.

Then I got curious: when programming a game with Unreal, what are the differences between using those 2 options and possibly what are the main cases when one should drop the standard C++ primitive in favor of the engine's implementation?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'd be interested in reading the examples you've found that actually use FFloat32. \$\endgroup\$
    – user1430
    Aug 15, 2016 at 15:29
  • \$\begingroup\$ @JoshPetrie Some of them were off-line, a couple were online. As soon as I have time at home, I will search for them to share \$\endgroup\$ Aug 15, 2016 at 22:06

1 Answer 1

17
\$\begingroup\$

float, is well, a C++ floating point. FFloat32 is a structure that represents a float as well as (via a union) the decomposed bitfields for that float's sign, mantissa and exponent parts.

You should generally never use FFloat32 except when:

  • you're using some API that expects a FFloat32 (these are very rare) or
  • you need to do some kind of low-level bit hackery with a floating point value (also fairly rare these days)

It's not that FFloat32 is bad, per se, it's just that it doesn't really offer you anything you'd need for general-purpose floating point usage.

It is less common than a plain old float, which has some minor readability impact (others may not know immediately what it is for at a glance). It also doesn't implicitly convert to float so you'll be typing something.FloatValue a lot, which is also not a big deal, but could get tedious.

Finally, its use of unions and bitfields is non-portable, and implementation-defined (see below). This is not your problem, it is Epic's job to make sure the type is structured so that it's usable for all supported implementations, but it's a potential source of bugs if they fail to catch an issue with the implementation of the type when a new compiler version is released or added to the list of supported compilers.

So unless you have a need to play with the individual bits in the floating point representation, you should probably just avoid FFloat32 (its cousin, FFloat16, may have slightly more utility as there is no standard 16-bit C++ floating point type).

It used to be common to manipulate floats via integer representations of their components for "speed." Modern computers obviate much of that need for many platforms, and the various type-punning techniques that could be used to do this sort of thing can actually be detrimental to performance or correctness in any event.

It should be telling that a search of Unreal's GitHub repository reveals very few uses of the FFloat32 type. All of them are in the the definition of FFloat32 itself or in the definition of FFloat16.


Specifically, FFloat32 does two things which the C++ standard calls out. It:

  • allows you to act as if more than one member of the union is active at one time; you are expected to write to the floating point members and read from one of the integer members (9.5.1, [class.union])
  • expects the bitfield allocation within the union to match that of the bit allocation of an IEEE floating point value; however, allocation and alignment of bitfield members within a class type is implementation defined (9.6.1, [class.bit])
\$\endgroup\$
7
  • \$\begingroup\$ Unreal is not written in standard C++, it's written for the particular compilers it's written for, so as long as they do the expected thing the standard is irrelevant. \$\endgroup\$
    – user253751
    Aug 15, 2016 at 6:00
  • \$\begingroup\$ I would expect those bitfields to be quite portable even in standard C/C++, since they are defined by an IEEE standard, and any compiler using a different layout for float would get not IEEE 754 compliant red mark (and compatibility troubles with lots of existing software). \$\endgroup\$ Aug 15, 2016 at 13:57
  • 3
    \$\begingroup\$ The (pedantic) issue is that the written order of those bit fields may match the IEEE standard, but the C++ compiler may reorder or re-align them. This is only a minor footnote though since dealing with that is Epic's job; they should monitor each new compiler version to verify the type works correctly. \$\endgroup\$
    – user1430
    Aug 15, 2016 at 13:59
  • \$\begingroup\$ @JoshPetrie Point taken, thanks for clarification. \$\endgroup\$ Aug 15, 2016 at 14:00
  • 1
    \$\begingroup\$ @JustinLardinois But FFloat32 contains a float member in the union, so if float is actually larger than 32 bits the overall FFloat32 will be as well since the union must be large enough to hold the biggest member. In cases where floats are bigger than four bytes Epic will have had to modify the bitfield parts of the union as well to address that, otherwise they won't map the complete float. \$\endgroup\$
    – user1430
    Aug 15, 2016 at 17:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .