4 ms·
Use unsigned integers, which have well-defined overflow behavior. In my experience with C (which is biased towards some specific use cases), most numbers that
by comex 6y ago
Use unsigned integers, which have well-defined overflow behavior.
In my experience with C (which is biased towards some specific use cases), most numbers that are likely to overflow are things like sizes and counts, which cannot meaningfully be negative anyway, so you may as well use unsigned integers for them. Other cases really do require signed integers, but for most arithmetic operations you can 'just' convert to unsigned before doing the arithmetic and then convert the result back to signed.
(Some may disagree. For instance, the Google C++ style guide [1] specifically says not to "use unsigned types to say a number will never be negative", because they want the undefined overflow behavior of signed types, in order to allow the compiler to diagnose bugs and to avoid "imped[ing] optimization". I think this is mostly nonsense; the drawbacks far outweigh the benefits, and tools for detecting overflow like UBSan can be told to check unsigned overflow as well.)
That said, even if you avoid the UB cases, checking for overflow correctly is hard; I've found many security vulnerabilities caused by missing or incorrect overflow checks. __builtin_add_overflow and friends are very nice if you have them, though unergonomic. I wish a more ergonomic version were standardized as part of the language.
[1] https://google.github.io/styleguide/cppguide.html https://google.github.io/styleguide/cppguide.html
- jcelerier 6y ago> (Some may disagree. For instance, the Google C++ style guide [1] specifically says not to "use unsigned types to say a number will never be negative", because they want the undefined overflow behavior of signed types, in order to allow the compiler to diagnose bugs and to avoid "imped[ing] optimization". I think this is mostly nonsense; the drawbacks far outweigh the benefits, and tools for detecting overflow like UBSan can be told to check unsigned overflow as well.) Yes, I really disagree. unsigned integers mean one thing, which is "modular arithmetic". Unless you are in the very uncommon case of actually needing modular arithmetic, for instance, when implementing a crypto or hash algorithm, you want normal integers. As soon as you have anything that may have any chance of introducing a substraction somewhere, unsigned will cause bugs. I don't know how many times I had to debug broken code such as for(int i = 0; i < some_size - 1; i++) { ... } because some_size was unsigned. If you really want a "number that cannot be negative", you don't wan't some_size - 1 to silently give you UINT_MAX, you want a type that will give you a compile-time or at worst run-time error.
- zelphirkalt 6y agoLets say some_size is the length or size of something. So that a negative number does not make sense, as there will only ever be a positive length or size (Is that actually the case for arrays and such?). Then how would you express that fact? What is your proposal for such a type?
- jcelerier 6y agothe way to do it has been known for years: https://groups.google.com/a/isocpp.org/g/std-proposals/c/-KVPhEKsEQY https://groups.google.com/a/isocpp.org/g/std-proposals/c/-KV...
- zelphirkalt 6y agoThank you for that. It is great, that this is known for years. I am not a regular C coder, so I am merely asking out of curiosity. Could you supply a non-Google link to example code? Perhaps in some git repository or a code snippet on a non-Google snippet website?
- Quekid5 6y agoHere's an example of a similar library: https://github.com/foonathan/type_safe https://github.com/foonathan/type_safe
- zelphirkalt 6y agoAha, thank you, that's pretty cool! I wonder how they manage to make these types zero-overhead.
- jcelerier 6y agoIt can't be zero-overhead over e.g. int a,b ; a+b; It's however zero-overhead wrt a+b plus the manual error checking you'd have to do if you wanted to be correct