[Info-vax] VMS Cobol - GnuCOBOL
Dan Cross
cross at spitfire.i.gajendra.net
Fri Mar 3 09:30:30 EST 2023
In article <k6e8a5Fu2e4U5 at mid.individual.net>,
bill <bill.gunshannon at gmail.com> wrote:
>On 3/3/2023 6:59 AM, Johnny Billquist wrote:
>> Damn! I learned something new today...
>>
>> On 2023-03-01 15:54, Dan Cross wrote:
>>> In article <ttnk0m$lg5$2 at news.misty.com>,
>>> Johnny Billquist <bqt at softjar.se> wrote:
>>>> On 2023-02-28 20:11, Dan Cross wrote:
>>
>> [...]
>>
>>>> You overcomplicated the whole explanation.
>>>
>>> Hmm.
>>
>> I was wrong. :-)
>>
>>>> Basically, if you multiply two numbers, and the result would be bigger
>>>> than the types involved, the result is undefined.
>>>
>>> Well...no. _unsigned_ integer overflow in C is well-defined (it
>>> has modular wrapping semantics; C11 sec 6.2.5 para 9).
>>> Similarly, overflow of signed atomics is well-defined (C11 sec
>>> 7.17.7.5 para 3), so this is not always true.
>>
>> I had actually missed that unsigned integers do have a defined overflow
>> behavior. Thanks.
>>
>>>> In this case, the type
>>>> is unsigned short. If the multiplication cause anything that don't fit
>>>> into an unsigned short, then the result is undefined.
>>>>
>>>> And it's fairly easy to find two unsigned short numbers that when
>>>> multiplied will give a result that don't fit into an unsigned short.
>>>
>>> The range of unsigned short has little to do with it, and
>>> truncation of the result is fine too (again, defined to use
>>> modular wrapping for unsigned types; C11 sec 6.3.1.3). The
>>> problem is entirely due to the promotion to _signed_ int prior
>>> to the multiplication. The fix, incidentally, is easy:
>>>
>>> unsigned short
>>> mul(unsigned short a, unsigned short b)
>>> {
>>> Â Â Â Â unsigned int aa = a, bb = b;
>>> Â Â Â Â return aa * bb;
>>> }
>>>
>>> This is well-defined, even if the range of `unsigned short` is
>>> the same as `unsigned int`, which is permitted by the standard.
>>
>> Right. My second error. It is allowed to promote a unsigned short to a
>> signed int.
>> I do feel that I don't entirely agree with that rule, but it's
>> definitely written as such.
>>
>> Changing from unsigned to signed feels just as a freedom too much.
>>
>>>> It's really not that different from any other language. Some languages
>>>> will throw an exception, others will just give some result that might or
>>>> might not be meaningful. But there is no guarantee in almost any
>>>> language of some kind of specific meaningful result. Try it in FORTRAN
>>>> and see what you get there, or Cobol (or BASIC). :-)
>>>
>>> The issue, and the reason for the complex initial explanation,
>>> is the subtle interaction between the implicit type promotion
>>> rules, arithmetic, undefined behavior, and the freedom that UB
>>> gives to compiler writers, which is pretty unique to C. Hence
>>> why optimizing compilers often _appear_ to introduce bugs when
>>> in fact they're performing perfectly legal transformations, and
>>> turning off the optimizer can appear to "fix" the problem.
>>
>> Yup. You were right. Sorry that I had to go and read the spec again.
>> Trusting my brain was obviously the wrong thing to do.
>>
>
>And it really doesn't matter whether the result is truncation,
>conversion to signed int, wrap around, throwing an exception or
>undefined. The answer is still going to be wrong and the calculation
>worthless. So, what's the point? Fix the damn code.
Bill, do you understand that there are application domains where
people want well-defined modular arithmetic on unsigned types?
You seem intent on dismissing this as a valid use case, by
repeatedly that the results are "worthless." As I pointed out
to you earlier in this thread, wrapping semantics can be very
useful.
>Go ahead, blame the language again.
Ok. I blame the language for having confuing semantics, and I
blame compiler writer for exploiting that at the expense of
programmers.
- Dan C.
More information about the Info-vax
mailing list