4 ms·
That is correct. A serious mistake in C. Go was designed by (among others) the father of Unix Ken Thompson, with an understanding of the mistakes of C and C++.
by bugfix-66 4y ago
That is correct. A serious mistake in C.
Go was designed by (among others) the father of Unix Ken Thompson, with an understanding of the mistakes of C and C++.
Another example is that Go requires explicit integer casts (disallowing implicit integer casts) to avoid what is now understood to be an enormous source of confusion and bugs in C.
You can understand Go as an improved C, designed for a world where parallel computing (e.g., dozens of CPU cores) is commonplace.
- wizeman 4y ago> A serious mistake in C. Well, that's arguable. This "mistake" could be fixed in C tomorrow without breaking the semantics of any existing C code, but notice that this hasn't been "fixed" in any of the latest C standards, so perhaps it's still there for a reason. And the reason it hasn't been "fixed" is that compilers can optimize code better if they can assume that signed addition won't overflow. So it's more of a trade-off rather than strictly being a disadvantage. It's also something you can "fix" in your own code if you want to, by passing a compiler flag (-fwrapv in gcc), although arguably, at that point your code wouldn't be strictly C-standard compliant anymore. Or by using some library that handles arithmetic overflow by wrapping around, which could be implemented in standard C. > Another example is that Go requires explicit integer casts (disallowing implicit integer casts) to avoid what is now understood to be an enormous source of confusion and bugs in C. I agree with you on this, although forcing explicit casts also makes the code more verbose and can make it harder to understand what's going on. I think a balanced approach is requiring explicit casts only for the "tricky" cases, i.e. when the values might become truncated, and possibly also when sign-extension might be necessary and therefore might result in something the programmer didn't expect. But if I were to design a language I'm not sure that I would require explicit casts for e.g. promoting a uint16_t to a uint32_t... > You can understand Go as an improved C, designed for a world where parallel computing (e.g., dozens of CPU cores) is commonplace. That's a bit of a hot take :) Let me know when the Linux kernel starts to get rewritten in Go ;)
- Gibbon1 4y ago> And the reason it hasn't been "fixed" is that compilers can optimize code better if they can assume that signed addition won't overflow. Everyone says that and they have no proof.
- wizeman 4y ago> Everyone says that and they have no proof. Here's an entire blog post with proof: https://kristerw.blogspot.com/2016/02/how-undefined-signed-overflow-enables.html https://kristerw.blogspot.com/2016/02/how-undefined-signed-o...
- Gibbon1 4y agoBlog post has theory but no performance measurements.
- wizeman 4y agoWell, then you have moved the goal post, because initially you didn't ask for performance measurements, you asked for proof that compilers can optimize code better if they can assume signed arithmetic won't overflow. And the blog post lists dozens of optimizations which can indeed be performed due to that decision. The benefits of these optimizations will vary depending on the actual code and on the architecture/CPU, of course. It will be greater for hot and tight loops that benefit from these optimizations and less important for cold parts of the code. It will also be greater for more limited CPUs and less important for more sophisticated ones.
- a1369209993 4y agoNone of that requires or even supports undefined overflow. > Signed integer expression simplification [...] This is easily addressed by allowing (but not requiring) implementations to keep wider intermediate results on signed overflow, to a unspecified width at least as wide as the operands. > the index calculations are typically done using 32-bit int No, they're done using size_t; that's what size_t is for. > undefined overflow ensures that a[i] and a[i+1] are adjacent. No, the fact that i (of type size_t) < length of a <= size of a in bytes <= SIZE_MAX ensures that a[i] and a[i+1] are adjacent. (Also, note that this does not mean the optimizer is allowed to access memory at &a[i+1], since that might be across a page boundary (or even the wraparound from address ...FFF to 0), which makes adjacency less helpful than one might hope.) > Value range calculations [...] Loop analysis and optimization [...] Allowed but not required to retain excess bits on signed overflow.