|
In the kernel developer world on the other hand, it's still very common to think about how the C code one writes translates into assembly. (Honestly, I think C should not be used much outside developing kernels anyway, and even there it's just legacy, but that's just personal opinion.) But it's rough, and dangerous. Optimizers do a lot these days, and I really mean a lot. Besides completely mangling your program order, which includes shoving entire blocks of code into places that you might not have guessed, they also do such things as leveraging undefined behavior for optimizations (what the article is partly about), or replacing entire bits of code by function calls. (A compiler might make code out of your memcpy(), and vice versa; the latter can be especially surprising.) If you care about the assembly representation of your C code (which kernel developers often do), you will spend a lot of time with the "volatile" keyword, compiler barriers, and some obscure "__attribute__"s. But I agree, even with those caveats in mind, it's a very useful skill to imagine your C code as what it translates to (even if that representation is just a simplified model of what the compiler will actually do). |
that is a poor way to handle UB as it introduces bugs (which are UB themselves). If a compiler detects UB, it should flag an error so the source code gets changed. compilers (or any software really) should never be maliciously compliant.