3 ms·
> You can just make it implementation defined No you can't. Let me repeat again. One very possible implementation is to crash on signed integer overflow (`-ftr
by grandempire 2y ago
> You can just make it implementation defined
No you can't. Let me repeat again. One very possible implementation is to crash on signed integer overflow (`-ftrapv`). But if it cannot easily detect it, then it must either: a) check every integer add. b) use some less reliable detection method (random sampling, etc).
To be well defined means the implementation will reliably do the same thing. A procedure which sometimes does one thing or another, is not well defined.
> Unsigned integer overflow doesn't have any conditionals either.
That's because there is no detection needed. The instruction set for unsigned integers is designed to do that.
> -fwrapv
Here is the documentation:
> This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation.
https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
What this means is that if your hardware wraps on signed integer overflow, you can tell GCC that you are perfectly happy with that behavior. Then GCC understands and will handle it just fine.
If your hardware does something else, `fwrapv` will not help you.
- dzaima 2y agoBut an implementation wouldn't choose to specify its behavior for an operation to be something that it knows it cannot do efficiently, if the goal is to be efficient, for extremely obvious reasons. If your hardware does twos complement, the compiler should choose to define the implementation-defined behavior to be twos complement. If the hardware traps, the implementation-defined behavior would be to trap. And so on. And, as long as the goal isn't to exploit the overflows for fancy optimizations unrelated to what the hardware does, that'll perfectly fine and produce code that doesn't do anything extra over what you'd expect, and won't ever summon cthulhu (as long as the behavior the implementation defines isn't to summon cthulhu). (that's all assuming that there's a single best definable specific behavior for a given op for a given architecture, which isn't actually true; e.g. ARM scalar shifts do `shift %= width`, but SIMD shifts shift the other direction on a negative amount, and give 0 on `abs(shift) >= width`, only looking at the low 8 bits of the shift amount)
- grandempire 2y agoYes, we are in complete agreement.
- eru 2y ago> (that's all assuming that there's a single best definable specific behavior for a given op for a given architecture, which isn't actually true; e.g. ARM scalar shifts do `shift %= width`, but SIMD shifts shift the other direction on a negative amount, and give 0 on `abs(shift) >= width`, only looking at the low 8 bits of the shift amount) In that case, your implementation defined behaviour could still be that your compiler is allowed to non-deterministically pick between any of the allowed behaviours. But nasal demons would still be verboten.
- grandempire 2y ago> your implementation defined behaviour could still be that your compiler is allowed to non-deterministically No. Non-determinism is a key difference between undefined and implementation defined. Remember back in school - a function is well defined if it has exactly one output for every input. Let me turn this question around since we keep going in circles. If the standard said the words you just said instead of “undefined” how would that make C better? Is there some bad implication I am missing?
- eru 2y ago> No. Non-determinism is a key difference between undefined and implementation defined. Actually, I think that's the difference in the C spec between implementation defined and unspecified. Eg function arguments can be evaluated in any order the compiler feels like, but it's not UB (because the only thing that's allowed to vary is the order, nasal demons are still verboten.) You are right that it seems like the C standard expects implementation defined behaviour to be deterministic. That's annoying and should probably be fixed. > If the standard said the words you just said instead of “undefined” how would that make C better? Is there some bad implication I am missing? A lot better! If you know that eg shifts (or signed integer addition) always produce a value (even if non-deterministically) out of a documented set of valid options, that would make your program much more easy to reason about for the programmer, than UB's nasal demons that fly back in time. Informally, many people already try to reason about their C programs like this. See also how eg malloc returns an address, but apart from some basic requirements on alignment etc, the spec doesn't specify what address gets returned: the implementation can pick non-deterministically.
- eru 2y ago> If your hardware does something else, `fwrapv` will not help you. Yes, and both you and your compiler know what your hardware is doing. If you have hardware that does something else, you could do another implementation defined thing. Eg one's complement or trapping or whatever it is your hardware is doing. >> Unsigned integer overflow doesn't have any conditionals either. > That's because there is no detection needed. The instruction set for unsigned integers is designed to do that. It's designed to do that on some (well, almost all) computers. Just like it's designed to do the same for signed integers. Most computers don't even have a special instruction for signed integer addition, because they are twos-complement machines. --- Implementation defined could also be: 'Do whatever your processor does with an 'add' instruction; but don't let anything weird travel backwards in time, or make additional assumptions about execution paths not happening.'
- grandempire 2y ago> Do whatever your processor does with an 'add' instruction; but don't let anything weird travel backwards in time, or make additional assumptions about execution paths not happening.' That’s exactly what the standard means by undefined. Anything more you are reading into it is an absurd hypothetical. If you find such an implementation - let me know so I can avoid it. Clang and gcc do reasonable things - as you have pointed out there are helpful flags to configure it too.
- formerly_proven 2y agoYeah you definitely wanna review section 3 of the C standard again because it literally doesn't say that lol
- grandempire 2y agoPlease read the context. let me quote myself > A conforming implementation may chose to melt your computer - and you can choose to not use that implementation. But clang and gcc will never melt your Linux. And for the 3rd time, a real world case that might ruin your computer is an embedded device without memory protection.