Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #67773 > unrolled thread

Re: the language (and the role of Undefined Behavior therein)

Started bysupercat@casperkitty.com
First post2015-08-18 16:19 -0700
Last post2015-08-20 23:41 -0700
Articles 20 on this page of 55 — 12 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-18 16:19 -0700
    Re: the language (and the role of Undefined Behavior therein) Richard Damon <Richard@Damon-Family.org> - 2015-08-18 21:15 -0400
      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-19 10:11 -0700
        Re: the language (and the role of Undefined Behavior therein) Ike Naar <ike@iceland.freeshell.org> - 2015-08-19 19:58 +0000
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-19 14:09 -0700
        Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-19 16:10 -0400
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-19 16:01 -0700
            Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-19 20:23 -0400
              Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-20 10:35 -0700
                Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-20 12:32 -0700
                  Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-20 13:31 -0700
                    Re: the language (and the role of Undefined Behavior therein) donalhambra@gmail.com - 2015-08-20 14:23 -0700
                      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-20 16:13 -0700
                    Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-20 17:48 -0700
                      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-21 01:32 -0700
                        Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-21 18:34 -0700
                          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-21 22:11 -0700
                            Re: the language (and the role of Undefined Behavior therein) Richard Damon <Richard@Damon-Family.org> - 2015-08-22 09:41 -0400
                              Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-22 16:59 +0000
                                Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-22 23:30 -0400
                                  Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-24 03:36 +0000
                                    Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-24 00:25 -0400
                                      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-23 22:57 -0700
                                        Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-24 19:49 +0000
                                  Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-09-06 14:43 -0700
                              Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-23 16:27 -0700
                                Re: the language (and the role of Undefined Behavior therein) Richard Damon <Richard@Damon-Family.org> - 2015-08-23 21:15 -0400
                                  Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-23 20:18 -0700
                            Re: the language (and the role of Undefined Behavior therein) raltbos@xs4all.nl (Richard Bos) - 2015-08-22 14:37 +0000
                          Re: the language (and the role of Undefined Behavior therein) David Kleinecke <dkleinecke@gmail.com> - 2015-08-22 19:12 -0700
                            Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-22 23:38 -0400
                              Re: the language (and the role of Undefined Behavior therein) David Kleinecke <dkleinecke@gmail.com> - 2015-08-23 20:01 -0700
                                Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-23 21:56 -0700
                                  Re: the language (and the role of Undefined Behavior therein) David Kleinecke <dkleinecke@gmail.com> - 2015-08-24 17:25 -0700
                                    Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-24 18:21 -0700
                                    Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-24 22:22 -0400
                                      Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-25 14:31 +0000
                                        Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-25 09:22 -0700
                                          Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-25 18:55 +0000
                                          Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-25 12:33 -0700
                                            Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-25 16:23 -0700
                                Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-24 00:31 -0400
                                  Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-08-24 10:32 -0700
                            Re: the language (and the role of Undefined Behavior therein) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-08-22 23:54 -0700
                            Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-08-24 03:45 +0000
                          Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-09-07 08:11 -0700
        Re: the language (and the role of Undefined Behavior therein) Richard Damon <Richard@Damon-Family.org> - 2015-08-23 18:46 -0400
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-23 19:04 -0700
            Re: the language (and the role of Undefined Behavior therein) Richard Damon <Richard@Damon-Family.org> - 2015-08-23 23:40 -0400
              Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-23 22:48 -0700
                Re: the language (and the role of Undefined Behavior therein) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-08-24 00:38 -0700
    Re: the language (and the role of Undefined Behavior therein) James Kuyper <jameskuyper@verizon.net> - 2015-08-18 21:22 -0400
    Re: the language (and the role of Undefined Behavior therein) Ike Naar <ike@iceland.freeshell.org> - 2015-08-20 21:44 +0000
      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-08-20 16:48 -0700
      Re: the language (and the role of Undefined Behavior therein) Philip Lantz <prl@canterey.us> - 2015-08-20 23:41 -0700

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#68186

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-08-24 03:36 +0000
Message-ID<mre3fs$b8d$1@speranza.aioe.org>
In reply to#68085
James Kuyper <jameskuyper@verizon.net> wrote:
> On 08/22/2015 12:59 PM, glen herrmannsfeldt wrote:

>> Most commonly discussed is the results from divide and mod with
>> one or two negative arguments. C might have changed this now, but
>> it used to be that two choices were allowed.
 
> Two choices were never allowed when both arguments are negative, only
> when one was negative and the other was positive, 

Yes, I didn't make that so obvious.

> and only in C90

I wasn't so sure, but I thought it had changed.
 
> In C99. integer division is described as truncating the fractional part,
> and a footnote clarifies that this means rounding toward 0. The
> mathematical value of -4/3 is -(1 1/3), truncating the fractional part
> gives -1. 

Since Fortran requires this, it isn't likely that processors
intended for scientific work will do it the other way.

It is the more obvious way for sign magnitude machines, which
generate the quotient and remainder, then apply the appropriate
sign.

> From the identity (a/b)*b + a%b == a, i follows that -4%-3 == -1.

-- glen

[toc] | [prev] | [next] | [standalone]


#68192

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-08-24 00:25 -0400
Message-ID<mre68i$6h7$2@dont-email.me>
In reply to#68186
On 08/23/2015 11:36 PM, glen herrmannsfeldt wrote:
> James Kuyper <jameskuyper@verizon.net> wrote:
...
>> In C99. integer division is described as truncating the fractional part,
>> and a footnote clarifies that this means rounding toward 0. The
>> mathematical value of -4/3 is -(1 1/3), truncating the fractional part
>> gives -1. 
> 
> Since Fortran requires this, it isn't likely that processors
> intended for scientific work will do it the other way.

C90 left it unspecified because there were existing processors (possibly
not "intended for scientific work") that did it the other way.

Personally, on those occasions when I wanted to calculate an integer
corresponding to a/b when a and b have opposite signs, I've always
wanted "round toward negative infinity", not "round toward 0", so I find
this specification inconvenient. However, having it inconveniently
specified was a substantial improvement over leaving it unspecified.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#68195

Fromsupercat@casperkitty.com
Date2015-08-23 22:57 -0700
Message-ID<25b983cf-2dc5-47b6-9e52-15d812437a1e@googlegroups.com>
In reply to#68192
On Sunday, August 23, 2015 at 11:25:39 PM UTC-5, James Kuyper wrote:
> Personally, on those occasions when I wanted to calculate an integer
> corresponding to a/b when a and b have opposite signs, I've always
> wanted "round toward negative infinity", not "round toward 0", so I find
> this specification inconvenient. However, having it inconveniently
> specified was a substantial improvement over leaving it unspecified.

Ironically, the one time I can think of where I actually wanted round-toward-
zero semantics, I was dividing by two on a compiler which didn't optimize for
that case, and the code was time-critical, which meant I had to use a shift
along with conditional logic to force the rounding.

Otherwise, I would posit that while a lot of hardware division instructions
follow FORTRAN's model, the opposite model would have resulted in more efficient
code in many cases.  Division by constants is extremely common, and in many
cases is most efficiently done without using a "divide" instruction.  In the
case of division by powers of two, most implementations provide a signed right
shift instruction for the task, but for other values the most efficient approach
is often a multiply/add/shift combination, which is made less efficient by
the requirement to treat negative numbers specially.

Because hardware divide instructions are generally slow, adding a little bit of
extra code for the negative-dividend case would be a relatively minor effect on
overall execution speed.  By contrast, because the multiply-and-shift is
faster, the relative effect of adding extra instructions to implement the
mandated round-toward-zero is greater.

[toc] | [prev] | [next] | [standalone]


#68260

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-08-24 19:49 +0000
Message-ID<mrfsfj$pe1$1@speranza.aioe.org>
In reply to#68195
supercat@casperkitty.com wrote:
> On Sunday, August 23, 2015 at 11:25:39 PM UTC-5, James Kuyper wrote:
>> Personally, on those occasions when I wanted to calculate an integer
>> corresponding to a/b when a and b have opposite signs, I've always
>> wanted "round toward negative infinity", not "round toward 0", so I find
>> this specification inconvenient. However, having it inconveniently
>> specified was a substantial improvement over leaving it unspecified.
 
> Ironically, the one time I can think of where I actually wanted 
> round-toward- zero semantics, I was dividing by two on a compiler 
> which didn't optimize for that case, and the code was time-critical, 
> which meant I had to use a shift along with conditional logic to 
> force the rounding.

Note that the results from signed shift are dependent on the 
representation of signed values.

Fortran originated on sign-magnitude machines.
 
> Otherwise, I would posit that while a lot of hardware division 
> instructions follow FORTRAN's model, the opposite model would have 
> resulted in more efficient code in many cases.  Division by 
> constants is extremely common, and in many cases is most 
> efficiently done without using a "divide" instruction.  In the
> case of division by powers of two, most implementations provide 
> a signed right shift instruction for the task, but for other values 
> the most efficient approach is often a multiply/add/shift 
> combination, which is made less efficient by the requirement to 
> treat negative numbers specially.

(snip)

-- glen

[toc] | [prev] | [next] | [standalone]


#69683

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-09-06 14:43 -0700
Message-ID<kfn7fo3ql48.fsf@x-alumni2.alumni.caltech.edu>
In reply to#68085
James Kuyper <jameskuyper@verizon.net> writes:

> On 08/22/2015 12:59 PM, glen herrmannsfeldt wrote:
> ...
>> Most commonly discussed is the results from divide and mod with
>> one or two negative arguments.  C might have changed this now, but
>> it used to be that two choices were allowed.
>
> Two choices were never allowed when both arguments are negative,
> only when one was negative and the other was positive, and only in
> C90 [snip]

The C90 part is right.  The part that choices were not allowed
when both arguments were negative is wrong.

[toc] | [prev] | [next] | [standalone]


#68163

Fromsupercat@casperkitty.com
Date2015-08-23 16:27 -0700
Message-ID<5012cf9c-80ee-4403-aa37-c6ebb4de1588@googlegroups.com>
In reply to#68007
On Saturday, August 22, 2015 at 8:41:10 AM UTC-5, Richard Damon wrote:
> > On the vast majority of platforms I've used, "n" would behave as something
> > that, each time it is read, will behave as some mathematical integer which
> > is congruent to a value one greater than MAX_INT, mod 2*MAX_INT+2.  I believe
> > the language would be enhanced enormously if such behavior were defined as
> > normative, such that compilers could opt to conform to it or not as they see
> > fit, but would require to indicate via macro or other such means whether or
> > not they do so.
> 
> Vast Majority != All.

How much of the code that is written today will anyone ever want to run on
hardware which could not support partially-indeterminate-value semantics with
zero extra cost [other than the loss of the ability to reverse-propagate
assumptions about values and make optimizations that could be made more easily
and safely via other means anyway].  Is anything gained by hobbling the 99.9%
of software will never have to run on hardware that can't support such
semantics?

> A prime guiding principle in the design of C was that it wanted to make 
> operators efficient, in other words, work at real hardware speeds, so 
> much undefined behavior results from real (or imagined like possible) 
> machine behavior. "Mod" behavior like you describe is common for a two's 
> complement machine with no trapping on overflow, which may be the 
> 'standard' now, but even now is not universal.

Given that the "mod" behavior I describe (as distinct from the behavior
implemented by the "wrapv" option in gcc) allows for compilers to retain
extra precision or not as they see fit, and allows comparisons involving
partially-indeterminate values to arbitrarily return true or false, I'd
be extremely surprised if there exist any hardware platforms which most
programmers would care about where the most straightforward methods of
performing arithmetic wouldn't satisfy such rules.

Can you name one?


> Wider behavior comes from machines that would 'Trap' on overflow, which 
> is a behavior so extreme that standard needed to define it as undefined 
> behavior. (without trapping, I think the standard could easily have 
> defined the results as an unspecified result.

I don't mind the existence of a trap on overflow if an implementation either
defines a means by which code can ensure that it will not cause code to
execute erroneously, or else does so by default; I would expect that even among
C implementations where overflows trap, the vast majority would be able to
uphold such a guarantee.

From the point of view of the Standard, if it would be possible for an action
to trigger a trap whose behavior might be outside the control of the running
program, there is no terminology to describe the effect of the action other
than Undefined Behavior.  Use of the term doesn't mean that implementations
which can implement and specify a useful behavior shouldn't endeavor to do so;
to the contrary, it allows whatever behavior would be optimal in the judgement
of the implementer.

> Note also, Standards don't define normative behavior that 
> implementations can choose to 'opt out'. You can have features 
> officially described as optional, normally with a standard specified 
> macro to detect that this optional feature is available.

Many standards do define normative behavior; many protocol documents denote
such behaviors with the words SHOULD and SHOULD NOT, written in all-caps.  Had
the C Standard been written in such fashion, a lot of problems and confusion
could have been avoided, especially if most "A compiler should do X" statements
were paired with "Compilers that don't do X must indicate that in fashion Y".
For example, "Compilers should, when practical, implement relational operators
in such fashion as to allow all pointers to be ranked in non-overlapping
fashion; compilers must define macro STDC_POINTER_COMPARE to indicate the effect
of comparing unrelated pointers."


> Note again, it is quite allowable for someone to define a language 
> extension to C, that when present, defines a number of things that C 
> leaves undefined, and using floating point as an example, the C 
> standards committee has shown a willingness to make such a standard as 
> an optional part of C. The key would be finding a large enough set of 
> behaviors to be useful and at the same point naturally supportable by a 
> large set of common machines.

For starters, I would suggest that 99% of software will never be called upon to
run on machines that couldn't support all of the following:

1. Integer overflow either yields partially-indeterminate value, traps so as
   to prevent further code execution, or traps in implementation-defined
   fashion that would allow the prevention of further code execution.  

2. Have memset behave like memmove in when the destination and source pointers
   are precisely equal (useful when the code required to skip the memcpy in
   the pointers-equal case would waste more time in the pointers-not-equal
   case than it would save in the pointers-equal case.

3. The pointer equality and inequality operators shall define an equivalence
   relation among pointers, regardless of the lifetime of the objects
   identified thereby; the fact that two pointers compare equal would not,
   however, imply that operations which would be defined on one would be
   likewise defined on the other.

Can you identify any modern platforms which would have any difficulty with any
of the above?

[toc] | [prev] | [next] | [standalone]


#68174

FromRichard Damon <Richard@Damon-Family.org>
Date2015-08-23 21:15 -0400
Message-ID<gfuCx.64234$rO6.56289@fx22.iad>
In reply to#68163
On 8/23/15 7:27 PM, supercat@casperkitty.com wrote:
> On Saturday, August 22, 2015 at 8:41:10 AM UTC-5, Richard Damon wrote:
>>> On the vast majority of platforms I've used, "n" would behave as something
>>> that, each time it is read, will behave as some mathematical integer which
>>> is congruent to a value one greater than MAX_INT, mod 2*MAX_INT+2.  I believe
>>> the language would be enhanced enormously if such behavior were defined as
>>> normative, such that compilers could opt to conform to it or not as they see
>>> fit, but would require to indicate via macro or other such means whether or
>>> not they do so.
>>
>> Vast Majority != All.
>
> How much of the code that is written today will anyone ever want to run on
> hardware which could not support partially-indeterminate-value semantics with
> zero extra cost [other than the loss of the ability to reverse-propagate
> assumptions about values and make optimizations that could be made more easily
> and safely via other means anyway].  Is anything gained by hobbling the 99.9%
> of software will never have to run on hardware that can't support such
> semantics?
>

To remove the undefined behavior for these cases would in effect say 
that processors that don't conform to the model defined can't have 
efficient version of C defined (and really inefficient C isn't really C).

There also is that fact that the Standard doesn't MAKE the 
implementation go against the partially-indeterminate-value semantics 
(and in fact as far as I know, all implementations can be put in a mode 
that supports this) as one possibility of undefined behavior is what is 
expected.

It would also be quite possible to define an extension (or something 
like Appendix F) to define that the implementation behaves in this sort 
of way. Making it an extension, says the programs that want that 
behavior just document (or even test for) the extension, and programs 
that want to be able to work on the more extreme hardware don't.

>> A prime guiding principle in the design of C was that it wanted to make
>> operators efficient, in other words, work at real hardware speeds, so
>> much undefined behavior results from real (or imagined like possible)
>> machine behavior. "Mod" behavior like you describe is common for a two's
>> complement machine with no trapping on overflow, which may be the
>> 'standard' now, but even now is not universal.
>
> Given that the "mod" behavior I describe (as distinct from the behavior
> implemented by the "wrapv" option in gcc) allows for compilers to retain
> extra precision or not as they see fit, and allows comparisons involving
> partially-indeterminate values to arbitrarily return true or false, I'd
> be extremely surprised if there exist any hardware platforms which most
> programmers would care about where the most straightforward methods of
> performing arithmetic wouldn't satisfy such rules.
>
> Can you name one?
>
>

Again, you are making the limitation of 'most'. I would say that most 
programmers wouldn't mind defining that they are writing to C + 
extension-simple-integer-math. The standards committee has traditionally 
taken the stance that it will not restrict the language in a way that 
makes it not possible to make a reasonable implementation of a new 
standard on a platform that is in use and could implement the previous 
standard, and I think this is good.

I HAVE used machines that would have problems with that definition as 
they were 1's complement math (so there would be a different mod value).

To propose that the standard drop support for such machines, it would 
fall on the proponent to show that those machines are no longer in 
active use (at least as far as C development is concerned).

>> Wider behavior comes from machines that would 'Trap' on overflow, which
>> is a behavior so extreme that standard needed to define it as undefined
>> behavior. (without trapping, I think the standard could easily have
>> defined the results as an unspecified result.
>
> I don't mind the existence of a trap on overflow if an implementation either
> defines a means by which code can ensure that it will not cause code to
> execute erroneously, or else does so by default; I would expect that even among
> C implementations where overflows trap, the vast majority would be able to
> uphold such a guarantee.
>
>  From the point of view of the Standard, if it would be possible for an action
> to trigger a trap whose behavior might be outside the control of the running
> program, there is no terminology to describe the effect of the action other
> than Undefined Behavior.  Use of the term doesn't mean that implementations
> which can implement and specify a useful behavior shouldn't endeavor to do so;
> to the contrary, it allows whatever behavior would be optimal in the judgement
> of the implementer.

Yes, "Undefined Behavior" is a very blunt instrument in the Standard, 
and likely many things defined as UB could perhaps be defined as 
unspecified behavior with a much broader range of possible behaviors 
(including possibly abrupt termination). I think the biggest issue would 
be for someone to come to the committee with the proper expertise to be 
able to come up with such a list of possible behaviors that encompass 
all viable architectures.

Note again, nothing stops an implementation for defining any of these 
behaviors, and in fact, most do have a compliant mode that does so for 
the cases you seem to be concerned in.


>> Note also, Standards don't define normative behavior that
>> implementations can choose to 'opt out'. You can have features
>> officially described as optional, normally with a standard specified
>> macro to detect that this optional feature is available.
>
> Many standards do define normative behavior; many protocol documents denote
> such behaviors with the words SHOULD and SHOULD NOT, written in all-caps.  Had
> the C Standard been written in such fashion, a lot of problems and confusion
> could have been avoided, especially if most "A compiler should do X" statements
> were paired with "Compilers that don't do X must indicate that in fashion Y".
> For example, "Compilers should, when practical, implement relational operators
> in such fashion as to allow all pointers to be ranked in non-overlapping
> fashion; compilers must define macro STDC_POINTER_COMPARE to indicate the effect
> of comparing unrelated pointers."
>

There is an inherent difference between a protocol standard and a 
language standard. The biggest is that protocols are normally between 
programs, and they will have the ability (if the protocol is well 
defined) to determine the compatible subset that both support.

For a language standard, the program can't normally adjust itself by 
asking the compiler its capability (although some optional features have 
things defined to let the program adjust). I one sense, the base 
standard defines the MUST, and the optional features are the SHOULD/MAY 
items.

>
>> Note again, it is quite allowable for someone to define a language
>> extension to C, that when present, defines a number of things that C
>> leaves undefined, and using floating point as an example, the C
>> standards committee has shown a willingness to make such a standard as
>> an optional part of C. The key would be finding a large enough set of
>> behaviors to be useful and at the same point naturally supportable by a
>> large set of common machines.
>
> For starters, I would suggest that 99% of software will never be called upon to
> run on machines that couldn't support all of the following:
>
> 1. Integer overflow either yields partially-indeterminate value, traps so as
>     to prevent further code execution, or traps in implementation-defined
>     fashion that would allow the prevention of further code execution.
>
> 2. Have memset behave like memmove in when the destination and source pointers
>     are precisely equal (useful when the code required to skip the memcpy in
>     the pointers-equal case would waste more time in the pointers-not-equal
>     case than it would save in the pointers-equal case.
>
> 3. The pointer equality and inequality operators shall define an equivalence
>     relation among pointers, regardless of the lifetime of the objects
>     identified thereby; the fact that two pointers compare equal would not,
>     however, imply that operations which would be defined on one would be
>     likewise defined on the other.
>
> Can you identify any modern platforms which would have any difficulty with any
> of the above?
>

I can't say I am enough of an expert on all platforms to know what 
implementations currently would have problems with them.

Note, for 1, some of your behaviors currently can only be Undefined 
Behavior, so until you (or somebody) can detail and expanded unspecified 
behavior you are stuck here.

For 2, I presume you mean memcpy. I will first say I am not sure that 
there isn't an architecture that wouldn't have an issue with matching 
pointers for the memory copy instruction. The cost of the compare and 
skip will be pretty small, so you need VERY small buffers to make the 
cost significant (and not doing much else of overwhelm the cost), at 
which point perhaps you could replace the memcpy with a direct 
assignment. (You also could directly implement the copy and let the 
optimizer convert it to the instruction)

For 3, I am not certain I understand your case, if it is the fact that 
looking at a pointer to free()ed memory is undefined behavior, that was 
primarily a factor in segmented memory, which is mostly gone now (but I 
believe the processors are still available), but I also can't think of a 
case where it would be important to be able to test such a value.

[toc] | [prev] | [next] | [standalone]


#68183

Fromsupercat@casperkitty.com
Date2015-08-23 20:18 -0700
Message-ID<048f7c90-b6e5-4d11-a5c8-cee98ea55e16@googlegroups.com>
In reply to#68174
On Sunday, August 23, 2015 at 8:16:04 PM UTC-5, Richard Damon wrote:
> To remove the undefined behavior for these cases would in effect say 
> that processors that don't conform to the model defined can't have 
> efficient version of C defined (and really inefficient C isn't really C).

My requirement would merely be that all compilers be required to define macros
which would allow programs to compile-time-assert their requirements, and
regard any regard any program whose requirements can't be met as ill-formed.
If a program starts with

    #include <tcsb.h>
    __TSCB_NORMATIVE_LL64
    __TCSB_REQUIRE(__TCSB_ANY_INT_OVERFLOW, __TCSB_PARTIALLY_INDETERMINATE)

then some compilers wouldn't be able to legitimately compile it, but that
would be no great loss since it wouldn't run correctly if compiled on them
anyway.  Any existing compiler which could naturally support the appropriate
semantics and allows any relevant command-line switches to be tested in any
fashion by the preprocessor could support the above code merely through the
addition of a suitable <tcsb.h> file.

> It would also be quite possible to define an extension (or something 
> like Appendix F) to define that the implementation behaves in this sort 
> of way. Making it an extension, says the programs that want that 
> behavior just document (or even test for) the extension, and programs 
> that want to be able to work on the more extreme hardware don't.

What I would want to see would be a requirement that compilers supply a <tcsb.h>
[Testably Constrained/Specified Behavior] file which would allow programs to
assert their needs, and require that compilers either meet those needs or
reject the program as ill-formed, along with a term to describe programs which
do not use any features or guarantees **which they have not asserted**.  At
present, the term "strictly-compliant" is almost useless, because only a tiny
fraction of useful programs could be practically written in such a fashion as
to work on all implementations meeting the C Standard.  By contrast, it should
be practical for most programs to list their requirements in machine-readable
fashion and guarantee correct operation on all platforms meeting those
requirements.

> Again, you are making the limitation of 'most'. I would say that most 
> programmers wouldn't mind defining that they are writing to C + 
> extension-simple-integer-math. The standards committee has traditionally 
> taken the stance that it will not restrict the language in a way that 
> makes it not possible to make a reasonable implementation of a new 
> standard on a platform that is in use and could implement the previous 
> standard, and I think this is good.

I have no objection to having the C language allow for implementations on
unusual platforms.  Indeed, I would have made "long long" optional for that
reason, since there are some platforms where support for that type would be
rather difficult.  While a compiler for an 8-bit micro could support that
types using lots of subroutine calls, in most cases programs would be better
served by coding such math other ways.

> I HAVE used machines that would have problems with that definition as 
> they were 1's complement math (so there would be a different mod value).
> 
> To propose that the standard drop support for such machines, it would 
> fall on the proponent to show that those machines are no longer in 
> active use (at least as far as C development is concerned).

I think you misunderstand my intention.

> Yes, "Undefined Behavior" is a very blunt instrument in the Standard, 
> and likely many things defined as UB could perhaps be defined as 
> unspecified behavior with a much broader range of possible behaviors 
> (including possibly abrupt termination). I think the biggest issue would 
> be for someone to come to the committee with the proper expertise to be 
> able to come up with such a list of possible behaviors that encompass 
> all viable architectures.

I don't think that's actually necessary.  The greatest benefits would be
achieved by recognizing the most widely-supported and most widely-used
behaviors.  While there might be some disputes over what behaviors should be
considered widely-enough used to be worthy of recognition, adding a behavior
to the list would simply mean that implementations would have to specify
whether or not they support it.  My suggested approach would be to define
macros associated with actions, and bit values associated with behaviors, and
then say that each action's macro should yield something that the preprocessor
would regard as an integer expression (possibly including preprocessor
intrinsics) which ORs together all of the behaviors that could result from that
action, or yields -1 if the behavior is totally undefined.

> Note again, nothing stops an implementation for defining any of these 
> behaviors, and in fact, most do have a compliant mode that does so for 
> the cases you seem to be concerned in.

The problem is that there is at present no standard way for a program to
compile-time assert that whatever compiler is being used with it is configured
to guarantee certain behaviors.

> There is an inherent difference between a protocol standard and a 
> language standard. The biggest is that protocols are normally between 
> programs, and they will have the ability (if the protocol is well 
> defined) to determine the compatible subset that both support.

A language is a protocol which involves, programmers, compilers, and
compiler writers.

> For a language standard, the program can't normally adjust itself by 
> asking the compiler its capability (although some optional features have 
> things defined to let the program adjust). I one sense, the base 
> standard defines the MUST, and the optional features are the SHOULD/MAY 
> items.

A lot of programs use #ifdef statements to adjust to compilers.  A program
which performs a lot of small memcpy operations, none of which will overlap
but a few of which might have the same source and destination, might do
something like:

#if __STDC_MEMCPY_MATCH_SOURCE_DEST & ~__STDC_MEMCPY_AS_MEMMOVE
    if (src != dest) memcpy(src, dest, 8);
#else
    memcpy(src, dest, 8);
#endif

If the programmer knows that the items will never partially overlap, but a
compiler couldn't know that, a guarantee that the memcpy will be safe in
cases where the source and destination coincide would allow the program to
save a pointer check that a compiler might not otherwise be able to optimize
out (if the pointers coincided half the time, the check might make the code
more efficient, but if they coincide 0.01% of the time and the source/dest
would be in cache even then, it would simply waste time; a compiler would be
unlikely to know which situation applied).

> > For starters, I would suggest that 99% of software will never be called upon to
> > run on machines that couldn't support all of the following:
> >
> > 1. Integer overflow either yields partially-indeterminate value, ...
> > 2. Have memset behave like memmove in when the destination and source pointers
> >     are precisely equal...
> >
> > 3. The pointer equality and inequality operators shall define an equivalence
> >     relation among pointers,...
> > Can you identify any modern platforms which would have any difficulty with any
> > of the above?
> >
> 
> I can't say I am enough of an expert on all platforms to know what 
> implementations currently would have problems with them.

> Note, for 1, some of your behaviors currently can only be Undefined 
> Behavior, so until you (or somebody) can detail and expanded unspecified 
> behavior you are stuck here.

I'm not quite sure what you mean?  The requirement for overflow would be
similar to what the Standard presently requires for narrowing integer
conversions except that:

1. The implementation would not be required to define a single value

2. The term "implementation-defined signal" is not defined by the standard
   (so far as I can tell) and the Standard does not make clear whether an
   implementation would have to define a means by which a program could use
   such a signal to force termination.

If your observation is that the requirements are in general too loose for
the term "Implementation-Defined" behavior or "Unspecified behavior" to be
used directly, I agree.  I'd propose "Testably-Constrained Behavior", and
I would also replace most "Implementation-Defined Behavior" with "Testably-
Specified Behavior", such that code could use:

__TCSB_REQUIRE(__TSCB_SIGNED_INT_DOWNCAST, __TCSB_TWOS_COMPLEMENT_REDUCTION)

and be assured that any conversion of an out-of-range value to a smaller
integer type would convert it to the corresponding unsigned type, and if the
result was out of range, subtract (2*INT_MAX+2).  At present, so far as I can
tell, nothing in the Standard requires implementatons that use two's complement
representation to do conversions in that fashion as opposed to e.g. having all
values greater than 32767 map to 32767.

> For 2, I presume you mean memcpy. I will first say I am not sure that 
> there isn't an architecture that wouldn't have an issue with matching 
> pointers for the memory copy instruction. The cost of the compare and 
> skip will be pretty small, so you need VERY small buffers to make the 
> cost significant (and not doing much else of overwhelm the cost), at 
> which point perhaps you could replace the memcpy with a direct 
> assignment. (You also could directly implement the copy and let the 
> optimizer convert it to the instruction)

There are many cases where the Strict Aliasing Rule necessitates the use of
memcpy/memmove for really small assignments; in many cases, compilers will
map memcpy to an intrinsic that replaces four- or eight-byte copy operations
involving known-aligned pointers with one or two load/store operations; some
compilers map memcpy to an intrinsic but don't do so with memmove.  There may
be some compilers that would trap, but the solution is to have compilers with
such behavior squawk at attempts to compile programs that have indicated such
behavior is unacceptable.

> For 3, I am not certain I understand your case, if it is the fact that 
> looking at a pointer to free()ed memory is undefined behavior, that was 
> primarily a factor in segmented memory, which is mostly gone now (but I 
> believe the processors are still available), but I also can't think of a 
> case where it would be important to be able to test such a value.

One situation I have in mind there would be one where a pointer to freed memory
is *supposed* to get nulled out, and one wishes to use a run-time check to
confirm that it indeed has been and flag a problem (and block the execution
of code which might have done bad things with it) if it hadn't.  In the event
that an execution path could reach the assertion code without the pointer
having been nulled out, having the optimzier regard the check as unreachable
could have effects worse than what would have occurred if the programmer had
omitted the assertion and code was only going to read the pointer rather than
write it (the read would likely either yield a value, or it would signal an
access exception, and either of those outcomes would be far less dangerous
than the creative rewriting an optimizer might perform.

Another situation, which would have somewhat narrower usefulness, would pertain
to platforms that can guarantee that if realloc returns a pointer equal to
the one which was passed in, all pointers to portions of that object would
remain valid.  Some segmented architectures couldn't make such a guarantee,
but some kinds of text-processing code may keep a list of pointers to the start
of each line of text. If the text moves, they could rescan the text and rebuild
the list, but if the text hasn't moved, such rescanning would be a waste of
effort.

[toc] | [prev] | [next] | [standalone]


#68019

Fromraltbos@xs4all.nl (Richard Bos)
Date2015-08-22 14:37 +0000
Message-ID<55d888b6.21149531@news.xs4all.nl>
In reply to#67980
supercat@casperkitty.com wrote:

> If C really wants to compete with Java and C#,

From where I'm sitting, it looks like it does that just fine - in part
exactly _because_ of the undefined behaviour newbies to the language so
often bewail in this newsgroup.

Richard

[toc] | [prev] | [next] | [standalone]


#68082

FromDavid Kleinecke <dkleinecke@gmail.com>
Date2015-08-22 19:12 -0700
Message-ID<026de000-b3bd-44b7-914e-0274671a3687@googlegroups.com>
In reply to#67971
On Friday, August 21, 2015 at 5:25:40 PM UTC-7, Keith Thompson wrote:
> The "hyper-modern philosophy" is the one that's been implicit in the C
> standard since 1989.  I haven't kept track of developments in optimization
> well enough to know how things have changed or when they've changed.
> But if your program has potential undefined behavior, I suggest that you
> need to fix the program.  If you think that
>     int n = INT_MAX;
>     n ++;
> "should" set n to any particular value, that's not a conclusion that you
> can draw from the C standard.
 
It might be better to explicitly recognize that C is not talking
about ordinary integers in the mathematical sense but rather arithmetic 
modulo INT_MAX+1. 

It is true that every computer I know about executes a multiplication
into a "register" twice as long as the multipliers. But C simply 
truncates that back modula INT_MAX+1 (actually it's bit more
complicated. Even though C provides no way getting the higher half
of a multiplication I enevr heard a complaint. Odd.   

[toc] | [prev] | [next] | [standalone]


#68086

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-08-22 23:38 -0400
Message-ID<mrbf41$mj9$1@dont-email.me>
In reply to#68082
On 08/22/2015 10:12 PM, David Kleinecke wrote:
...
> It might be better to explicitly recognize that C is not talking
> about ordinary integers in the mathematical sense but rather arithmetic 
> modulo INT_MAX+1. 

C's int type doesn't follows the rules of mathematical integers, and the
standard has never claimed that it did, so that would not be a change.
It's also not  required to follow the rules of arithmetic modulo
INT_MAX+1; so that would be a change. C is deliberately intended to be
implementable (and has been implemented) on platforms where following
those rules would be excessively difficult.

Unsigned int follows the rules of arithmetic modulo UINT_MAX+1; that
might be what you're thinking about.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#68181

FromDavid Kleinecke <dkleinecke@gmail.com>
Date2015-08-23 20:01 -0700
Message-ID<2340e1b4-d142-4a20-986b-089e9f712c9c@googlegroups.com>
In reply to#68086
On Saturday, August 22, 2015 at 8:38:24 PM UTC-7, James Kuyper wrote:
> On 08/22/2015 10:12 PM, David Kleinecke wrote:
> ...
> > It might be better to explicitly recognize that C is not talking
> > about ordinary integers in the mathematical sense but rather arithmetic 
> > modulo INT_MAX+1. 
> 
> C's int type doesn't follows the rules of mathematical integers, and the
> standard has never claimed that it did, so that would not be a change.
> It's also not  required to follow the rules of arithmetic modulo
> INT_MAX+1; so that would be a change. C is deliberately intended to be
> implementable (and has been implemented) on platforms where following
> those rules would be excessively difficult.
> 
> Unsigned int follows the rules of arithmetic modulo UINT_MAX+1; that
> might be what you're thinking about.
> -- 
> James Kuyper

Signed arithmetic is also a version of modulo UINT_MAX+1 with a
different way of writing some of the integers.

[toc] | [prev] | [next] | [standalone]


#68185

FromKeith Thompson <kst-u@mib.org>
Date2015-08-23 21:56 -0700
Message-ID<lna8thz3lo.fsf@kst-u.example.com>
In reply to#68181
David Kleinecke <dkleinecke@gmail.com> writes:
> On Saturday, August 22, 2015 at 8:38:24 PM UTC-7, James Kuyper wrote:
>> On 08/22/2015 10:12 PM, David Kleinecke wrote:
>> ...
>> > It might be better to explicitly recognize that C is not talking
>> > about ordinary integers in the mathematical sense but rather arithmetic 
>> > modulo INT_MAX+1. 
>> 
>> C's int type doesn't follows the rules of mathematical integers, and the
>> standard has never claimed that it did, so that would not be a change.
>> It's also not  required to follow the rules of arithmetic modulo
>> INT_MAX+1; so that would be a change. C is deliberately intended to be
>> implementable (and has been implemented) on platforms where following
>> those rules would be excessively difficult.
>> 
>> Unsigned int follows the rules of arithmetic modulo UINT_MAX+1; that
>> might be what you're thinking about.
>
> Signed arithmetic is also a version of modulo UINT_MAX+1 with a
> different way of writing some of the integers.

No, it isn't.  C doesn't specify wraparound behavior for signed
integers; signed integer overflow has undefined behavior.

If by "signed arithmetic" you mean something other that what's specified
by C (such as, perhaps, the signed arithmetic operations implemented by
some particular CPU), you should make that clear.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#68280

FromDavid Kleinecke <dkleinecke@gmail.com>
Date2015-08-24 17:25 -0700
Message-ID<d1225caa-a905-4e5c-b318-0fc3a4c7df08@googlegroups.com>
In reply to#68185
On Sunday, August 23, 2015 at 8:30:00 PM UTC-7, Keith Thompson wrote:
> David Kleinecke <dkleinecke@gmail.com> writes:
> > On Saturday, August 22, 2015 at 8:38:24 PM UTC-7, James Kuyper wrote:
> >> On 08/22/2015 10:12 PM, David Kleinecke wrote:
> >> ...
> >> > It might be better to explicitly recognize that C is not talking
> >> > about ordinary integers in the mathematical sense but rather arithmetic 
> >> > modulo INT_MAX+1. 
> >> 
> >> C's int type doesn't follows the rules of mathematical integers, and the
> >> standard has never claimed that it did, so that would not be a change.
> >> It's also not  required to follow the rules of arithmetic modulo
> >> INT_MAX+1; so that would be a change. C is deliberately intended to be
> >> implementable (and has been implemented) on platforms where following
> >> those rules would be excessively difficult.
> >> 
> >> Unsigned int follows the rules of arithmetic modulo UINT_MAX+1; that
> >> might be what you're thinking about.
> >
> > Signed arithmetic is also a version of modulo UINT_MAX+1 with a
> > different way of writing some of the integers.
> 
> No, it isn't.  C doesn't specify wraparound behavior for signed
> integers; signed integer overflow has undefined behavior.

All the C90 standard says is "The result of the binary + operator is 
the sum of the the operands." "Sum" is nowhere defined. I haven't found any discussion of "overflow".  

> If by "signed arithmetic" you mean something other that what's specified
> by C (such as, perhaps, the signed arithmetic operations implemented by
> some particular CPU), you should make that clear.
 
I doubt that any CPU does other than arithmetic modulo-two-to-the- 
number-of-bits-power. Different CPU's set different sets of flags - 
so the interpretations can differ.  

[toc] | [prev] | [next] | [standalone]


#68285

FromKeith Thompson <kst-u@mib.org>
Date2015-08-24 18:21 -0700
Message-ID<lnpp2cxiws.fsf@kst-u.example.com>
In reply to#68280
David Kleinecke <dkleinecke@gmail.com> writes:
> On Sunday, August 23, 2015 at 8:30:00 PM UTC-7, Keith Thompson wrote:
>> David Kleinecke <dkleinecke@gmail.com> writes:
[...]
>> > Signed arithmetic is also a version of modulo UINT_MAX+1 with a
>> > different way of writing some of the integers.
>> 
>> No, it isn't.  C doesn't specify wraparound behavior for signed
>> integers; signed integer overflow has undefined behavior.
>
> All the C90 standard says is "The result of the binary + operator is
> the sum of the the operands." "Sum" is nowhere defined. I haven't
> found any discussion of "overflow".

C90 6.3, 5th paragraph (C11 6.5p2 changes "exception" to "exceptional
condition"):

    If an *exception* occurs during the evaluation of an expression
    (that is, if the result is not mathematically defined or not
    representable), the behavior is undefined.

This applies to signed and floating-point types, but not to
unsigned types, since the standard explicitly defines the result
of an unsigned operation whose mathematical value is outside the
range of the type (C90 6.1.2.5, C11 6.2.5p9).

>> If by "signed arithmetic" you mean something other that what's
>> specified by C (such as, perhaps, the signed arithmetic operations
>> implemented by some particular CPU), you should make that clear.
>  
> I doubt that any CPU does other than arithmetic modulo-two-to-the-
> number-of-bits-power. Different CPU's set different sets of flags -
> so the interpretations can differ.

CPUs that use one's-complement or sign-and-magnitude almost certainly
do not operate that way.  I believe some CPUs can be configured
to trap on overflow, or to do other odd things like saturating.
I concede that such behavior is rare, but you did say "any CPU".

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#68288

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-08-24 22:22 -0400
Message-ID<mrgjdt$k9t$1@dont-email.me>
In reply to#68280
On 08/24/2015 08:25 PM, David Kleinecke wrote:
...
> I doubt that any CPU does other than arithmetic modulo-two-to-the- 
> number-of-bits-power. Different CPU's set different sets of flags - 
> so the interpretations can differ.  

Real world machines use 1's complement and sign-magnitude
representations of signed integers. There aren't as many as there were
in the ancient times when your favorite version of the C standard was
new, but there are still some. Both representations have the feature
that an n-bit object using that representation can only represent 2^n-1
different values. That's because both representations have a bit pattern
that is either a trap value or represents negative zero - it's up to the
implementation to decide which (saying so explicitly, is, I believe, new
in C99; in C90 the same thing is allowed (but not mandated) simply
because the standard fails to say anything to prohibit it). For integer
types, negative zero is considered by the C standard to merely be a
different representation of the same value as positive zero, so they
must produce the same results in all ordinary arithmetic operations
(bitwise operations are a different matter).

I have no idea what real-world 1's complement and sign-magnitude systems
do on overflow, but following the rules of arithmetic modulo 2^n isn't
an available option - those rules require the ability to represent 2^n
different values.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#68312

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-08-25 14:31 +0000
Message-ID<mrhu7e$dq8$1@speranza.aioe.org>
In reply to#68288
James Kuyper <jameskuyper@verizon.net> wrote:

(snip)

> Real world machines use 1's complement and sign-magnitude
> representations of signed integers. There aren't as many as there were
> in the ancient times when your favorite version of the C standard was
> new, but there are still some. Both representations have the feature
> that an n-bit object using that representation can only represent 2^n-1
> different values. That's because both representations have a bit pattern
> that is either a trap value or represents negative zero - it's up to the
> implementation to decide which (saying so explicitly, is, I believe, new
> in C99; in C90 the same thing is allowed (but not mandated) simply
> because the standard fails to say anything to prohibit it). For integer
> types, negative zero is considered by the C standard to merely be a
> different representation of the same value as positive zero, so they
> must produce the same results in all ordinary arithmetic operations
> (bitwise operations are a different matter).

The CDC supercomputers, such as the 6600 and 7600 are ones complement,
but rare today. I believe there is a C compiler for them.

Unisys still sells ones complement machines, and has a C compiler
for them.

The last of the sign magnitude machines that I know about,
and fairly popular at the time, are the IBM 7090 and 7094.
As far as I know, there is not a C compiler for them.

There are pretty much two ways to make a ones complement adder.
One compares -0 equal to +0, the other never generates -0 when
the inputs are never -0. This allows for the trap representation,
and doesn't complicate the ALU when comparing zeros.
 
> I have no idea what real-world 1's complement and sign-magnitude systems
> do on overflow, but following the rules of arithmetic modulo 2^n isn't
> an available option - those rules require the ability to represent 2^n
> different values.

If they don't trap on overflow, I believe it is modulo 2**N-1.

-- glen

[toc] | [prev] | [next] | [standalone]


#68324

Fromsupercat@casperkitty.com
Date2015-08-25 09:22 -0700
Message-ID<845e7b1a-6704-4512-a635-657e7924b7dc@googlegroups.com>
In reply to#68312
On Tuesday, August 25, 2015 at 9:31:26 AM UTC-5, glen herrmannsfeldt wrote:
> There are pretty much two ways to make a ones complement adder.
> One compares -0 equal to +0, the other never generates -0 when
> the inputs are never -0. This allows for the trap representation,
> and doesn't complicate the ALU when comparing zeros.

It's also worth noting that a two's-complement C compiler could also make
-INT_MAX-1 be a trap representation, and in some cases might save a little code
by defining INT_MIN to be -MAX_INT rather than -INT_MAX-1.

Actually, although I don't know of any processors that presently support such
semantics, it would for many applications be helpful if a processor had either
had versions of arithmetic instructions which treated 0x800000000 as NaN, or
had load instruction which would interpret that bit pattern as NaV (not
a value), arithmetic instructions which would silently propagate NaV, and a
store instruction which would silently store NaV as 0x80000000.  Unfortunately,
for 32-bit platforms to efficiently extend such semantics to "long long", the
the Standard would have to allow for `LONG_LONG_MIN` to be 0x8000000100000000
rather than 0x8000000000000000, so as to allow code to compute the lower word
of each result without examining the upper word, and I doubt the Committee
would go for that.

[toc] | [prev] | [next] | [standalone]


#68334

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-08-25 18:55 +0000
Message-ID<mridnr$o3c$2@speranza.aioe.org>
In reply to#68324
supercat@casperkitty.com wrote:
> On Tuesday, August 25, 2015 at 9:31:26 AM UTC-5, glen herrmannsfeldt wrote:
>> There are pretty much two ways to make a ones complement adder.
>> One compares -0 equal to +0, the other never generates -0 when
>> the inputs are never -0. This allows for the trap representation,
>> and doesn't complicate the ALU when comparing zeros.
> 
> It's also worth noting that a two's-complement C compiler could also make
> -INT_MAX-1 be a trap representation, and in some cases might save a 
> little code by defining INT_MIN to be -MAX_INT rather than -INT_MAX-1.
 
> Actually, although I don't know of any processors that presently 
> support such semantics, it would for many applications be helpful 
> if a processor had either had versions of arithmetic instructions 
> which treated 0x800000000 as NaN, or had load instruction which 
> would interpret that bit pattern as NaV (not a value), 
> arithmetic instructions which would silently propagate NaV, 
> and a store instruction which would silently store NaV as 0x80000000.  

Seems to me that it wouldn't be hard to do the test in software, 
thought might be a little slower than some might like.

(snip on long long)

-- glen

[toc] | [prev] | [next] | [standalone]


#68335

FromKeith Thompson <kst-u@mib.org>
Date2015-08-25 12:33 -0700
Message-ID<lnd1ybxix9.fsf@kst-u.example.com>
In reply to#68324
supercat@casperkitty.com writes:
> On Tuesday, August 25, 2015 at 9:31:26 AM UTC-5, glen herrmannsfeldt wrote:
>> There are pretty much two ways to make a ones complement adder.
>> One compares -0 equal to +0, the other never generates -0 when
>> the inputs are never -0. This allows for the trap representation,
>> and doesn't complicate the ALU when comparing zeros.
>
> It's also worth noting that a two's-complement C compiler could also
> make -INT_MAX-1 be a trap representation, and in some cases might save
> a little code by defining INT_MIN to be -MAX_INT rather than
> -INT_MAX-1.

(Just to mention, you wrote "MAX_INT" rather than "INT_MAX").

Note that making -INT_MAX-1 a trap representation doesn't mean that any
operation that yields that value has to "trap".  It merely means that
such an operation has undefined behavior.

An implementation with 32-bit 2's-complement signed int could have:

    #define INT_MIN (-2147483647)
    #define INT_MAX   2147483647

and then document that -2147483648 is a trap represenation, and
make no other changes.  If printf("%d\n", INT_MIN-1) happens to
"work", that's just one possible consequence of undefined behavior.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web