5 ms·
I agree with the factual things that you said (e.g. "entire program execution was meaningless"). Some stuff was hyperbolic ("time-travel back to the start of th
by nayuki 4y ago
I agree with the factual things that you said (e.g. "entire program execution was meaningless"). Some stuff was hyperbolic ("time-travel back to the start of the universe, delete it").
> [compilers] will make transformations to the program whose effects could manifest before the UB-having code executes [...] It's monumentally rude to us poor programmers who have bugs in our programs.
The first statement is factually true, but I can provide a justification for the second statement which is an opinion.
Consider this code:
void foo(int x, int y) {
printf("sum %d", x + y);
printf("quotient %d", x / y);
}
We know that foo(0, 0) will cause undefined behavior because it performs division by zero. Integer division is a slow operation, and under the rules of C, it has no side effects. An optimizing compiler may choose to move the division operation earlier so that the processor can do other useful work while the division is running in the background. For example, the compiler can move the expression x / y above the first printf(), which would totally be legal. But then, the behavior is that the program would appear to crash before the sum and first printf() were executed. UB time travel is real, and that's why it's important to follow the rules, not just make conclusions based on observed behavior.
https://blog.regehr.org/archives/232 https://blog.regehr.org/archives/232
- vikingerik 4y ago> Integer division is a slow operation, and under the rules of C, it has no side effects. Then C isn't following this rule - crashing is a pretty major side effect.
- Dylan16807 4y agoSide effects are a type of defined behavior. Crashing is not a "side effect" in C terms.
- t0mas88 4y agoOnly non-zero integer division is specified as having no side effects. Division by zero is in the C standard as "undefined behavior" meaning the compiler can decide what to do with it, crashing would be nice but it doesn't have to. It could also give you a wrong answer if it wanted to. Edit: And just to illustrate, I tried in clang++ and it gave me "5 / 0 = 0" so some compilers in some cases indeed make use of their freedom to give you a wrong answer.
- zerocrates 4y agoThe basic deal is that in the presence of undefined behavior, there are no rules about what the program should do. So if you as a compiler writer see: we can do this optimization and cause no problems _except_ if there's division by zero, which is UB, then you can just do it anyway without checking.
- vikingerik 4y agoTo my downvoters, since I can no longer edit: I've been corrected that the rule is integer division has no side effects except for dividing by zero. This was not the rule my parent poster stated.
- a1369209993 4y ago> I've been corrected No you haven't. The incorrect statement was a verbatim quote from nayuki's post, which you were responding to. Please refrain from apologising for other people gaslighting you (edit: particularly, but not exclusively, since it sets a bad precedent for everyone else).
- nayuki 4y agoAt the CPU level, division by zero can behave in a number of ways. It can trap and raise an exception. It can silently return 0 or leave a register unchanged. It might hang and crash the whole system. The C language standard acknowledges that different CPUs may behave differently, and chose to categorize division-by-zero under "undefined behavior", not "implementation-defined behavior" or "must trap". I wrote: > Integer division is a slow operation, and under the rules of C, it has no side effects. This statement is correct because if the divisor is not zero, then division truly has no side effects and can be reordered anywhere, otherwise if the divisor is zero, the C standard says it's undefined behavior so this case is irrelevant and can be disregarded, so we can assume that division always has no side effects. It doesn't matter if the underlying CPU has a side effect for div-zero or not; the C standard permits the compiler to completely ignore this case.
- a1369209993 4y ago> I wrote: > > Integer division is a slow operation, and under the rules of C, it has no side effects. Yes, you did, and while that's a reasonable approximation in some contexts, it is false in the general case, since division by zero has a side effect in the form of invoking undefined behaviour. (Arguably that means it has every possible side effect, but that's more of a philosophical issue. In practice it has various specific side effects like crashing, which are specific realizations of its theoretical side effect of invoking undefined behaviour.) vikingerik's statement was correct: > [If "Integer division [...] has no side effects",] Then C isn't following this rule - crashing is a pretty major side effect.
- salawat 4y ago...Why is the compiler reordering so much? Look. I get it, clever compilers (I guess) make everyone happy, but are absolute garbage for facilitating program understanding. I wonder if we are shooting ourselves in the foot with all this invisible optimization.
- saagarjha 4y agoPeople like fast code.
- knodi123 4y agoIn 2022, is there any other reasons to use C besides "fast code" or "codebase already written in C"?
- wnoise 4y ago"codebase already written in C" includes both "all the as yet unwrapped libraries" and "the OS interface".
- bluecalm 4y agoThere isn't. Fast code is pretty important though to a lot of people while security isn't (games, renderers, various solvers, simulations etc.). It's great C is available for that. If you're ok with slow use Java or whatever.
- int_19h 4y agoNo, and, in fact, the first one isn't valid - you can use C++ (or a subset of it) for the same performance profile with less footguns. So really the only time to use C is when the codebase already has it and there is a policy to stick to it even for new code, or when targeting a platform that simply doesn't have a C++ toolchain for it, which is unfortunately not uncommon in embedded.