7 ms·
> if (n && m > (size_t)-1/n) Am I the only one that doesn’t think this is “sweet”? I mean I know what it does and why and how it works, but IMHO a good langua
by noncoml 4y ago
> if (n && m > (size_t)-1/n)
Am I the only one that doesn’t think this is “sweet”?
I mean I know what it does and why and how it works, but IMHO a good language should let you express your intention and algorithm in human terms and logic in which there is no -1 value for an unsigned integer type.
- haberman 4y agoAgreed that it would be better if C had standardized versions of GCC's overflow checking functions: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Integer-Overflow-Builtins.html https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Integer-Overflo... With these functions, it could be written as: if (__builtin_mul_overflow(n, m, &n))
- saagarjha 4y agoC23 has ckd_mul.
- jwilk 4y agohttps://thephd.dev/c-the-improvements-june-september-virtual-c-meeting#n2683---towards-integer-safety https://thephd.dev/c-the-improvements-june-september-virtual...
- raverbashing 4y agoTrue. It seems the C committee at some point makes things harder than they should. And true, the C committee is not preventing anyone from using something else (Another reason why we should retire C for most projects)
- klodolph 4y ago> It seems the C committee at some point makes things harder than they should This seems like entirely the wrong way of looking at it to me. The C committee is not trying to make things harder than they should be, but they’re really just a committee in charge of C. Their goal isn’t to make C into some kind of beautiful safe language, it’s just to provide incremental improvements to C for the benefit of people stuck using it for whatever reason. Like, the C committee isn’t trying to stop you from retiring C. They’re just trying to help out the people who aren’t retiring C, for whatever reason—which could be toolchain availability (lots of architectures out there, you may only have a C compiler for some), could be so they can work with a legacy codebase, could be that some other tooling or process they have works with C (the various “safe C” / analyzable subsets or formal verification processes).
- raverbashing 4y agoI agree that in terms of modern proposals there's a lot of "doing what we can" However, leaving the overflow check/behavior on the multiplication as "implementation defined" seems like a bad call to me
- klodolph 4y agoThe fact that signed overflow is undefined is unfortunately something that is necessary for certain optimizations to be valid. You can, for example, try `-fwrapv` or `-ftrapv` on GCC, but if you run through an extensive benchmark suite you’ll see regressions. Not everyone cares about the benchmarks, but enough do.
- salawat 4y ago...Weren't we talking unsigned though?
- pjmlp 4y agoWG14 could take care about improving the language gotchas for safer software, something that all other ISO language groups, including WG21 do bother to do. However in 40 years they already made their point not to care beyond make C a portable macro assembler with more UB issues than writing in raw Assembly.
- klodolph 4y agoC is not even remotely like a macro assembler. I get why people make the comparison, but the more I work with C and assembler, the more I realize that the comparison is facile. The relationship between the C code you write and the machine code which the compiler generates is complicated. If you think of C as a portable assembler, it’s easy to draw the wrong conclusion about how your code will behave. You look at some code and think, “I know how the assembly should look,” and at that point you’ve lost, because of the vast gulf between C and assembly semantics. The UB issues are not going away. Some people who use C need to get good performance out of it. If you try fixing the UB issues, you end up having to remove optimization passes from your C compilers. That’s just not viable—hence, UB issues are here to say. The correct thing for the C committee is to make slow, careful improvements to C for the people who are stuck using it. And the correct choice for most people is to stop using C in favor of safer languages. If you try to have the committee fix the safety problems with C, you’re going to end up with something which neither fast nor safe. If you are stuck using C and need it to be safe, you can use formal methods. If you don’t have the budget for formal methods, you need safety, and you’re stuck on a system which only has a C toolchain, then the alternative is to use something which compiles to C.
- kazinator 4y agoThat language is C99, a now 23-year-old standard dialect of C. if (n && m > SIZE_MAX / n)
- vbezhenar 4y agoThere's SIZE_MAX constant, I don't know why they didn't use it. I'd rewrite it as `if (n != 0 && m > SIZE_MAX / n)`. Seems legit to me.
- pjmlp 4y agoMost likely to get around clever UB optimizations when checking for values beyond max sizes.
- caf 4y agoNo. (size_t)-1 and SIZE_MAX are identical, there is no difference in the two ways of writing that. Furthermore, optimisation can't bite you if you test the values before you perform the potentially UB operation (and unsigned operations can never overflow anyway, they are always well-defined).
- pjmlp 4y agoThat was just an assumption, far from me to know all UB cases, I leave that for tooling.
- mafuy 4y agoBut there is no such check here, is there? SIZE_MAX / SIZE_MAX is legally 1.
- AceJohnny2 4y agoMaybe it's late but I don't get it. Can someone spell it out for me?
- wruza 4y agoIf n != 0 and -1 cast to unsigned size_t divided by n is less than m. So that m times n would be bigger than size_t’s maximum value. Edit: inverted meaning since check is for error, not for ok case.
- dannymi 4y agoYou want to evaluate p in: p = m n If that is gonna overflow, p > SIZE_MAX. Then it would be that (by substitution) m n > SIZE_MAX so m > SIZE_MAX/n except if n = 0. In the latter case, m can be as big as it wants--p will always evaluate to 0. And (size_t)-1 is a silly way to write SIZE_MAX (but it saves you a dependency).
- AceJohnny2 4y agoThanks! Indeed the `(size_t)-1` threw me off, and the `m && n` was an interesting obfuscation for checking whether either are 0.
- zoomablemind 4y ago> if (n && m > (size_t)-1/n) Shouldn't the case of wraparound be caught by testing the resulting size as following? s = n*m; if (n && s >= n && s >= m) /* no overflow */ ...
- CUViper 4y agoThat doesn't work for multiplication -- e.g. in 8-bit, 20 * 20 wraps to 144.
- salawat 4y agoYou are not.