3 ms·
`spriteframe_t` is defined as typedef struct { // If false use 0 for any position. // Note: as eight entries are available, // we might as wel
by Sharlin 9mo ago
`spriteframe_t` is defined as
typedef struct
{
// If false use 0 for any position.
// Note: as eight entries are available,
// we might as well insert the same name eight times.
boolean rotate;
// Lump to use for view angles 0-7.
short lump[8];
// Flip bit (1 = flip) to use for view angles 0-7.
byte flip[8];
} spriteframe_t;
which is okay to splat with all-ones as long as `boolean` is either a typedef for a fundamental type(*) or an enum – because C enums are just ints in a trenchcoat and have no forbidden bit patterns! The C99 `bool`/`_Bool` is, AFAICS, the first type in C that has fewer values than possible bit patterns.
So yeah, on C99 and C++ this always had UB and could've broken at any time – though I presume compiler devs were not particularly eager to make it ill-behaved just because. But in pre-C99 it's entirely fine, and `rotate == true || rotate == false` could easily be false without UB.
---
(*) other than `char` for which setting the MSB is… not UB but also not the best idea in general.
- zozbot234 9mo agoC99 does not use bool unless you explicitly include stdbool.h, which won't be in any pre-C99 code. By default, you just get _Bool.
- direwolf20 9mo agoMaybe changing the type of the variable to int was the better solution?
- pwagland 9mo agoAnd, indeed, if you look at the author's writeup, you see exactly that the generated code satisifes `(rotate == true || rotate == false) == false`, since rotate is checked explicitly against 0 and 1. The essence of the difference is: > When boolean is an enum, the compiler does exactly what I expected – the == false condition checks if the value is equal to 0, and the == true condition checks if the value is equal to 1. > However, when boolean is actually _Bool, the == false check is transformed into != 1, and the == true check is transformed into != 0 – which makes perfect sense in the realm of boolean logic. But it also means that for a value of 255, hilarity ensures: since 255 is neither 0 nor 1, both conditions pass! So a value of 255 also makes both checks fail for the enum, but because of the ordering of the code, it was expected to evaluate as != false. Had the check: ``` if (sprtemp[frame].rotate == false) ``` been written as: ``` if (sprtemp[frame].rotate != true) ``` then it would work for the `bool` type, but not the `enum` type, at least in C23 mode. Assumedly the C++ mode (effectively) treated the boolean as an enum, or possibly as `false == 0`, `true != 0`.