Yes, this is inconsistent - but I can't think of any language that doesn't have this inconsistency:
No it is not. Read my reply above:
It is consistent, since floats in FreePascal are proper value types, so cardinal(v)
converts to cardinal, not reinterpret the value, whereas PCardinal(*v)^
uses the address directly.
And it is really only because FPC strengthened its type system.
This is a good thing and perfectly consistent.
What it is, is a trap for people coming from languages that do not have a strong type system, like C, and try to translate C code to Pascal.
Then it bites.
A cleaner way to flip the sign is simply v := v * -1 or
var
v: single = pi;
c: cardinal absolute v;
begin
writeln ('default value: ', v);
c := c xor $80000000;
writeln(v);
end.
You can also verify that v := v * -1 generates the exact same assembler as the casting fest. I used {$I-}{$OPTIMIZATION LEVEL4}
Languages with proper value types like Freepascal include C#, Java, Kotlin, Python, Haskell, Ada. But not C, C++ and the likes.
(And Rust and Go without unsafe also use proper value types).
To summarize: to flip the sign as in the original question, simply multiply by -1 otherwise use pointer dereferences.