In languages were data races are possible you can have every thread only ever increment x, and yet x's value will decrease due to a data race.
Python's GIL will protect against data races, meaning that certain classes of bugs where a specific memory location takes on a completely arbitrary value will never be observed from a Python program.
That would be a very strange language, or a very strange machine.
In particular integer reads and writes are atomic (though not necessarily well ordered) on x86, arm, etc, so you'd be hard pressed to get a C compiler to emit code that tears the reads or writes in a way that would lead to integer decrements.
You can't dereference a non-aligned pointer in portable C. It will bus error on certain architectures (including some arm variants).
(I've written plenty of code that relies on unaligned reads, and also that relies on non-torn reads/writes, just not at the same time, and never when portability was a concern.)
If you wish to discuss x86 or ARM, well a data race can occur in a C program through the use of SIMD instructions or writing through an unaligned pointer. If you want to pick an architecture that does not allow unaligned accesses, sure we can discuss the PowerPC 500 series where unaligned accesses are a bus error, but then reads and writes of 32 bit values are not atomic and hence can produce data races.
We can't mix properties of one architecture with properties of another architecture and also discuss portable C. Any consideration of data races or undefined behavior in general must be specific to a particular architecture and we must apply the rules of any given architecture consistently.
x starts as 0.
Thread A evaluates x + 1, getting 1.
Thread B executes the full statement 100 times, setting x to 100.
Thread A finishes executing the statement, setting x to 1.
So x decreased from 100 to 1.
But I agree with you that this is a race condition, not a data race.