3 ms·
And this is the biggest reason I still use C over C++, along with less UB and better compilation times. But please change the standard to disallow 00UB: https
by gavinhoward 2y ago
And this is the biggest reason I still use C over C++, along with less UB and better compilation times.
But please change the standard to disallow 00UB:
https://gavinhoward.com/2023/08/the-scourge-of-00ub/ https://gavinhoward.com/2023/08/the-scourge-of-00ub/
I have to do a lot of stuff to avoid UB in my code. I even implemented UB-free two's complement arithmetic using unsigned types just to avoid all of the problems.
And it has definitely gone too far when people think that the compiler doing anything on UB is the definition of UB, not just a side effect.
- deleted 2y ago[deleted]
- uecker 2y agoI am trying my best. As a first step, C23^1 will have this clarification: "Note 3 to entry: Any other behavior during execution of a program is only affected as a direct consequence of the concrete behavior that occurs when encountering the erroneous or non-portable program construct or data. In particular, all observable behavior (5.1.2.4) appears as specified in this document when it happens before an operation with undefined behavior in the execution of the program." ^1 https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
- gavinhoward 2y agoThis is good, but it actually makes it seem like time travel was a thing before C23.
- uecker 2y agoIt is non-normative note, as such it is to be understood as a clarification of what the standard already said before C23.
- uecker 2y agoRegarding signed overflow, I find it extremely useful that it is UB which allows me to instruct the compiler to insert a trap. This is very helpful to find bugs. For the same reason, the Linux kernel community (or some of them) want an attribute what would make overflow of annotated unsigned types also be UB.
- gavinhoward 2y agoI can do that without UB. In fact, I implemented wrapping, trapping, and saturation semantics in my arithmetic.
- int_19h 2y agoIt can be done as a library, but that is far less ergonomic than having the checks for actual arithmetic operators. However, I think that consistency should win here. Given that unsigned arithmetic already wraps around - and this cannot be changed for backwards compatibility reasons - making signed arithmetic do something different is just bad design. It would certainly be better if the default behavior was to trap rather than wraparound or saturate, but, well, we're talking here about a language that is >50 years old, so that ship has sailed. It would sure be nice to get proper dedicated operators for trapping and saturating arithmetic in some future version of the C standard, though.
- uecker 2y agoWhat is consistent depend on the perspective. For me signed integers are a model for integers and overflow means that I exceeded the capabilities of the machine to model those correctly. Unsigned is a model for modulo arithmetic. Wrapping signed integer would not model anything useful.
- int_19h 2y agoIf signed ints were truly a model for true mathematical integers, they would be unbounded (as in e.g. Python). C is low-level enough that it's not particularly useful to think in those terms, IMO. If you're writing in C, it's usually for one of the two reasons: either you want to be "close to the metal" because you're doing low-level stuff, or it's a legacy codebase. From the first perspective, I can't think of any "modern" - as in, past three decades - architecture for which signed wraparound is not the default & fastest behavior. From the second perpective, a lot of legacy code actually assumes signed wraparound (because compilers used to just defer to what the hardware actually did). FWIW the reason why C had UB for signed overflow historically is because back when it was being standardized, there were still machines around that used something other than two's complement to represent signed values. The original ANSI C89 straight up refused to specify the signed representation, and C99 narrowed it down to several options; thus, the obvious hardware implementation would in fact produce different results on overflow. Conversely, unsigned integers always had a well-defined representation for which wraparound was simply the natural hardware behavior. I don't think this was ever meant to have some kind of higher meaning. Given that C23 explicitly mandates two's complement for signed now, IMO, the signed overflow behavior should just be made consistent with that as well as real-world hardware. The only claimed downside to this is that compilers can no longer "optimize" code that was previously broken but would now be well-defined, but I don't see why that is an actual problem.