Save bytes in float variable

There is.

C++20 standard [basic.life.7]:

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways.
For an object under construction or destruction, see 11.10.5. Otherwise, such a glvalue refers to allocated storage (6.7.5.5.2), and using the properties of the glvalue that do not depend on its value is well-defined.
The program has undefined behavior if:
(7.1) — the glvalue is used to access the object, or
(7.2) — the glvalue is used to call a non-static member function of the object, or
(7.3) — the glvalue is bound to a reference to a virtual base class (9.4.4), or
(7.4) — the glvalue is used as the operand of a dynamic_cast (7.6.1.7) or as the operand of typeid.

[class.union.general.2, 6]:

In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended (6.7.3). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

When the left operand of an assignment operator involves a member access expression (7.6.1.5) that nominates a union member, it may begin the lifetime of that union member [...]

When you do type punning using a union, you access an object whose lifetime has not yet begun or has ended, which is undefined behavior.

To me "undefined" does not necessarily mean that the behaviour is undefined under all conditions.

That's not what it means to the language designers and compiler developers. Somewhat ironically, the standard does define what undefined behavior is:

undefined behavior
behavior for which this document imposes no requirements
[Note 1 to entry: Undefined behavior may be expected when this document omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression (7.7) never exhibits behavior explicitly specified as undefined in Clause 4 through Clause 15. — end note]

See also the link I posted earlier.

If you look back I wrote that "I prefer", so it's a matter of taste and experience what other people do and suggest.

You can choose to ignore this advice, but to argue that it is a matter of interpretation or personal taste is simply false.

That would invoke undefined behavior as well. Float and integers/bytes are not similar types, so you cannot cast a pointer/reference to int to a pointer/reference to float (if you dereference the result):

[basic.lval.11]:

If a program attempts to access (3.1) the stored value of an object through a glvalue whose type is not similar (7.3.6) to one of the following types the behavior is undefined:
(11.1) — the dynamic type of the object,
(11.2) — a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
(11.3) — a char, unsigned char, or std::byte type.

You cannot reason about memory in the same way an assembly programmer would. There is a compiler between your C++ source code and the code that is actually executed.