Raymond Chen has the best write up on UB that I've seen: <https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=63...>.
In addition to the "obvious" undefined behavior, strict aliasing is subtle and poorly understood in my experience. Consider the following:
Foo ReadFooFromBytes(const char* data, size_t len) {
Foo foo;
assert(len == sizeof(Foo));
foo = *(const Foo*)(data);
return foo;
}
Foo ConvertToFoo(Bar bar) {
return ReadFromBytes((const char*)&bar, sizeof(bar));
}
The `ReadFooFromBytes()` function could exhibit undefined behavior, depending on the provenance of its pointer parameter.If you gave it a pointer to a true array of chars, it's fine. If you use `ConvertToFoo()`, big bada boom. Truly baffling stuff, the first time you encounter it.
This kind of ties into the argument made by some in the Rust community that "the ownership was there the whole time" -- in a language without automatic memory management, you really do need to be aware of the life-cycle of an object in memory. Rust's specific rules aren't fundamental, but "even when an error occurs, I know what cleans up this object / this state" is.
C is very different from most other languages, I would say the closest one is actually Assembly.
I've been working on a book for a while now to try and share some of the ideas I've picked up over the years:
At least with some bare metal Forth you can inspect the machine from high level to ASM levels.
I often recommend beginners to learn all of Forth, C, Lisp & SmallTalk. Because they're all conceptually clean local maximums in the language design space.
Even Subleq+Eforth it's fine, you'll learn EForth (it can be set at muxleq.fth/subleq.ftj with some compatibility with do...loop and floats) and Subleq as a VM. It's highly documented and it even has a book to play with.
EDIT: as a nice example, I had some pas.f example with a Pascal triangle. In order to get it working under eforth, I just had to define .r as u.r on top like:
: .r u.r ;
and that was it. It ran on both PForth and EForth. Eforth on a subleq (muxleq for performance) under an n270 Atom netbook.