Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #93363 > unrolled thread
| Started by | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| First post | 2016-09-10 14:23 -0700 |
| Last post | 2016-09-13 07:47 -0700 |
| Articles | 20 on this page of 171 — 17 participants |
Back to article view | Back to comp.lang.c
Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-10 14:23 -0700
Re: Portable 16 bit binary integer write Barry Schwarz <schwarzb@dqel.com> - 2016-09-10 17:11 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-11 07:00 -0700
Re: Portable 16 bit binary integer write Richard Damon <Richard@Damon-Family.org> - 2016-09-13 08:41 -0400
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-13 06:24 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-13 16:19 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-13 10:20 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-13 11:07 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-13 20:47 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-14 08:24 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-15 12:17 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-15 11:27 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-15 09:03 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-15 11:21 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-15 18:39 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-15 12:26 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-15 23:12 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-15 16:17 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-15 18:35 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-16 11:10 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-16 08:43 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-16 19:59 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-16 13:34 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-16 16:23 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-16 15:31 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-16 19:06 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-16 23:27 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-17 15:04 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-17 20:35 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-18 00:09 -0700
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-18 19:36 +0100
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-18 15:29 -0700
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-19 01:20 +0100
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-18 09:48 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-18 19:38 +0200
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-18 15:33 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-18 13:58 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-18 14:15 -0700
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-18 23:15 +0100
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-18 15:46 -0700
Re: Portable 16 bit binary integer write Ian Collins <ian-news@hotmail.com> - 2016-09-19 17:03 +1200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-19 07:40 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 10:54 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 10:51 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 22:03 +0200
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 15:44 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-20 09:02 +0200
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-19 21:12 +0100
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 15:58 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 09:49 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-19 02:37 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 13:20 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-19 06:22 -0700
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-19 12:46 +0100
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 16:20 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-19 07:32 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 11:26 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-19 09:10 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-19 09:33 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-19 11:54 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 22:14 +0200
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-19 22:12 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-19 14:32 -0700
Re: Portable 16 bit binary integer write Robert Wessel <robertwessel2@yahoo.com> - 2016-09-19 22:58 -0500
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-20 09:45 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-20 07:49 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-20 19:43 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-20 11:15 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-19 22:36 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 21:30 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-22 23:58 -0700
Re: Portable 16 bit binary integer write Ian Collins <ian-news@hotmail.com> - 2016-09-23 19:45 +1200
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 08:17 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-28 09:59 -0700
Re: Portable 16 bit binary integer write Ian Collins <ian-news@hotmail.com> - 2016-09-29 07:59 +1300
Re: Portable 16 bit binary integer write Ike Naar <ike@iceland.freeshell.org> - 2016-09-28 19:26 +0000
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-28 12:37 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-10-09 03:46 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-18 13:53 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-21 21:03 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-21 22:23 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-22 08:09 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 10:31 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-23 10:56 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-29 08:03 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-30 07:39 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-22 09:49 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-22 08:34 -0700
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-22 17:44 +0100
Re: Portable 16 bit binary integer write Melzzzzz <Melzzzzz@zzzzz.com> - 2016-09-22 17:16 +0000
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-22 18:26 +0100
Re: Portable 16 bit binary integer write Melzzzzz <Melzzzzz@zzzzz.com> - 2016-09-22 17:33 +0000
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-23 10:23 +0200
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-23 13:43 +0100
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-23 14:58 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-22 18:14 -0700
Re: Portable 16 bit binary integer write luser droog <luser.droog@gmail.com> - 2016-09-22 20:28 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-23 00:12 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-22 10:57 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-23 10:18 +0200
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 11:48 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-23 15:58 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-29 08:21 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-30 07:42 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-23 23:38 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-24 11:42 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-24 14:13 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-24 23:03 -0700
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-25 11:29 +0100
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 14:02 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-25 15:17 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 16:52 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 13:59 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-25 15:13 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 15:50 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 08:13 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-24 16:06 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-24 11:53 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-24 14:23 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 14:16 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-25 15:18 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-25 16:39 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-25 23:33 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-26 02:08 -0700
Re: Portable 16 bit binary integer write Richard Heathfield <rjh@cpax.org.uk> - 2016-09-26 10:25 +0100
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-26 03:05 -0700
Re: Portable 16 bit binary integer write Richard Heathfield <rjh@cpax.org.uk> - 2016-09-26 11:09 +0100
Re: Portable 16 bit binary integer write "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-09-26 09:29 -0700
Re: Portable 16 bit binary integer write Richard Heathfield <rjh@cpax.org.uk> - 2016-09-26 17:37 +0100
Re: Portable 16 bit binary integer write "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-09-26 12:29 -0700
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-26 11:12 +0100
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-26 13:19 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-26 18:34 -0700
Re: Portable 16 bit binary integer write Ike Naar <ike@iceland.freeshell.org> - 2016-09-27 06:43 +0000
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-27 00:51 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-27 08:42 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-22 11:40 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 10:00 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-23 10:34 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-29 08:13 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-18 00:06 +0200
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-17 17:32 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-18 15:57 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-17 20:46 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-18 16:08 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-18 10:03 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-17 23:59 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-17 16:49 -0700
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-18 01:19 +0100
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-18 07:16 -0700
Re: Portable 16 bit binary integer write "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-18 10:19 -0400
Re: Portable 16 bit binary integer write luser droog <luser.droog@gmail.com> - 2016-09-18 13:26 -0700
Re: Portable 16 bit binary integer write "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-18 17:04 -0400
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 01:21 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-15 12:07 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-16 00:32 +0200
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-15 16:30 -0700
Re: Portable 16 bit binary integer write Keith Thompson <kst-u@mib.org> - 2016-09-15 18:35 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-15 22:00 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-15 22:17 -0700
Re: Portable 16 bit binary integer write Ian Collins <ian-news@hotmail.com> - 2016-09-16 18:12 +1200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-16 00:46 -0700
Re: Portable 16 bit binary integer write Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-16 10:23 +0100
Re: Portable 16 bit binary integer write BartC <bc@freeuk.com> - 2016-09-16 10:59 +0100
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-16 04:13 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-16 08:58 -0700
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-16 10:16 -0700
Re: Portable 16 bit binary integer write Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-16 09:11 -0700
Re: Portable 16 bit binary integer write David Brown <david.brown@hesbynett.no> - 2016-09-16 20:14 +0200
Re: Portable 16 bit binary integer write Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-16 20:37 -0700
Re: Portable 16 bit binary integer write supercat@casperkitty.com - 2016-09-13 07:47 -0700
Page 2 of 9 — ← Prev page 1 [2] 3 4 5 6 7 8 9 Next page →
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-16 08:43 -0700 |
| Message-ID | <2cf666d7-0755-4c70-adad-07dbafc2b2e7@googlegroups.com> |
| In reply to | #93607 |
On Friday, September 16, 2016 at 4:11:09 AM UTC-5, David Brown wrote:
> On 16/09/16 01:17, supercat wrote:
> > 1. The authors of the Standard expected that if some actions had usefully-
> > defined behaviors on implementations for many platforms but not quite
> > all, categorizing the action as UB would maintain the status quo; they
> > didn't think it would make the behaviors "less defined" than they had
> > been before the Standard was written.
>
> They called such behaviours "implementation defined", not "undefined".
> They did this where they thought compilers should behave in a sensible
> and predictable way, but that the best choice of behaviour would vary
> between implementations.
That's popular myth #2. The term "Implementation-Defined" is only used
in cases where *ALL* implementations are required to specify a precise
behavior. It is not used in cases where 99% of implementations might be
expected to define a specific behavior, but where it was deemed plausible
that some implementations might not be able to.
As evidence, I offer the fact that shifting a negative number left is UB
even though so far as I can tell every two's-complement machine (i.e. the
majority of C implementations) implements them the same way.
> And they made it perfectly clear that "undefined behaviour" does /not/
> mean "launch nasal daemons" or "screw the programmer" - it merely means
> "this standard does not define the behaviour". Implementations have
> always been free to add their own behaviour in such cases - and
> implementations have always done so. In some cases, that will be
> "assume it never happens and optimise from there", in other cases it
> will be "/this/ is how the code behaves".
In the years before C89, the C language was defined largely by precedent,
and while the Standard Library was not always consistently defined, the
behavioral precedents for the language itself were very strongly established
for implementations targeting machines that were architecturally like the
PDP-11 (except for details of data formats and alignment). Compilers may
offer *options* to waive certain behavioral expectations, but the fundamental
core of the language that was popular treated things as defined. Further,
the nature of "optimize from there" has changed quite fundamentally.
It would not be astonishing, for example, for an optimizer to have integer
overflow yield a result which differs from the correct result by some
arbitrary multiple of (INT_MAX*2+2). On an 8086, the multiply instruction
takes two 16-bit operands and always yields a 32-bit result in two specific
registers. Given something like:
long mul_add_l(unsigned char x, unsigned char y, long l)
{ return x*10000+y*7000+65536L; }
the most efficient code would interpret the bottom 16 bits of one product
as an unsigned number, but use all 32 bits of the other. While I would
be surprised if any compilers of that era would actually find the most
efficient code, I would not be in any way astonished if they did so, nor
would I be astonished if a compiler added the lower 16 bits of the two
products, sign-extended the result, and added that to l. If any result
which is congruent to the correct result mod 65536 would be equally
satisfactory, letting the compiler select among the calculation approaches
would be a clear win for optimization. By contrast, writing the expression
as "(unsigned)x*10000+(unsigned)y*7000+65536L;" would force the compiler
to generate less-than-optimal code [and would also spend almost as many
characters in the source text preventing the compiler from launching nuclear
missiles as it spent doing useful work].
> If a particular compiler implemented something (with undefined behaviour
> in the standards) in one way, and then changed how it implemented it,
> then that is an issue between the compiler, its documentation, and its
> users. If the compiler changed its documented behaviour, then that
> could be a surprise to the user - but if the user has been relying on
> undocumented behaviour, then they are at fault.
Specifications for things generally won't bother promising not to do
something unless the spec-writer can imagine someone thinking such a
behavior was plausible. For example, if a future version of gcc were
to generate nonsense machine code when a program uses type punning, even
when using -fno-strict-aliasing, should the programmer be faulted for
relying upon behavior that was never defined (gcc's documentation for
-fno-strict-aliasing doesn't actually promise that pointer-based type
punning will behave as though writing a pointer converts an object to a
series of bytes, and reading a pointer interprets the underlying bytes
as an object).
>
> >
> > 2. One of the authors' priorities was to ensure that if a pre-C89
> > implementation for platform X could perform some task with some level
> > of efficiency, it should be possible for a C89 compiler for that same
> > platform to do so just as well.
>
> This is something they wanted, but it was never an overriding priority.
> Code correctness trumps code speed every time - and the C standards
> committee, compiler writers, and any decent programmer knows this.
>
> >
> > 3. The authors of the Standard expected that it would be fairly clear and
> > obvious to programmers and compiler writers alike what behavioral
> > guarantees should be offered on what platforms, and that such people
> > would be better equipped than the authors of the Standard to make such
> > judgments.
>
> That sounds like compiler documentation to me.
>
> >
> > Have you seen evidence to contradict the above?
>
> I have never seen anything to support it - "proof by repeated assertion"
> aside.
>
> >
> > Have you seen any evidence to suggest that the authors of C89 intended
> > that programmers for commonplace platforms should ever have to jump
> > through hoops to achieve semantics which were consistently supported by
> > general-purpose implementations in 1988?
>
> I have never seen any evidence to suggest that people have been forced
> to jump through hoops to make their correct pre-C89 code remain correct
> post-C89.
>
> I have seen a few examples from you about how code written with ancient
> tools happened to work at the time, but fails to work with more advanced
> modern compilers. That is simply a matter of the older tools having far
> fewer optimisations - the code was never guaranteed to work from the
> documented behaviour of the tools. And on modern tools, you generally
> have a range of options and extensions that give you all the control you
> need in order to get the code results you want.
>
> >
> >> I will happily agree that it would be more
> >> convenient for /me/ if certain parts of the standard were nailed down in
> >> the way /I/ want them, rather than being left as implementation defined
> >> or undefined behaviour. But the standard writers are not writing the
> >> standards for /me/.
> >
> > The Standard isn't written to include all the behaviors you might want
> > on any given platform because it isn't intended to describe all of the
> > behaviors that a good implementation for any given platform should
>
> Ah, there you have written something that is true.
>
> But as Keith says, start a blog. Then you won't have to keep posting
> these lists of incorrect assumptions and theories again and again, and
> when people add comments correcting you, there is a slight chance that
> you will learn from them.
Probably not a bad idea, though I should mention that I have learned a fair
amount here.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-16 19:59 +0200 |
| Message-ID | <nrhbt5$l7r$1@dont-email.me> |
| In reply to | #93631 |
On 16/09/16 17:43, supercat@casperkitty.com wrote:
> On Friday, September 16, 2016 at 4:11:09 AM UTC-5, David Brown wrote:
>> On 16/09/16 01:17, supercat wrote:
>>> 1. The authors of the Standard expected that if some actions had usefully-
>>> defined behaviors on implementations for many platforms but not quite
>>> all, categorizing the action as UB would maintain the status quo; they
>>> didn't think it would make the behaviors "less defined" than they had
>>> been before the Standard was written.
>>
>> They called such behaviours "implementation defined", not "undefined".
>> They did this where they thought compilers should behave in a sensible
>> and predictable way, but that the best choice of behaviour would vary
>> between implementations.
>
> That's popular myth #2. The term "Implementation-Defined" is only used
> in cases where *ALL* implementations are required to specify a precise
> behavior. It is not used in cases where 99% of implementations might be
> expected to define a specific behavior, but where it was deemed plausible
> that some implementations might not be able to.
>
Making up numbers and claims does not help your argument.
> As evidence, I offer the fact that shifting a negative number left is UB
> even though so far as I can tell every two's-complement machine (i.e. the
> majority of C implementations) implements them the same way.
Left-shift of a negative number /is/ defined, as long as its value makes
sense. Perhaps you should read the standards before complaining about them.
The general rule for signed integers and their operations is that their
/value/ is significant, not their representation. Operations are
defined as long as the value makes sense.
-5 << 3 is defined to -5 * 2³, which is -40. It is only overflow of
signed integer shifts that is undefined behaviour. This is consistent
with all other arithmetic operations on signed integers.
Now, it would have been /possible/ for the C standards folks to say that
signed overflow was implementation dependent, not undefined behaviour.
However, they specifically choose undefined behaviour to give compiler
writers scope for optimisations - while also allowing compiler writers
to give defined behaviour if they wanted.
And how does every two's complement machine implement left shifting of
negative numbers? As long as the result does not lead to overflow, they
will all do it in the same way - they will follow the C standards. If
it leads to overflow, then who knows what they will do - I certainly
would not assume it is consistent. Certainly the behaviour for when the
shift amount is too big (greater than or equal to the width of the type)
will vary from processor to processor, and perhaps vary depending on
whether the value is known at compile time or not.
>
>> And they made it perfectly clear that "undefined behaviour" does /not/
>> mean "launch nasal daemons" or "screw the programmer" - it merely means
>> "this standard does not define the behaviour". Implementations have
>> always been free to add their own behaviour in such cases - and
>> implementations have always done so. In some cases, that will be
>> "assume it never happens and optimise from there", in other cases it
>> will be "/this/ is how the code behaves".
>
> In the years before C89, the C language was defined largely by precedent,
No, it was defined largely by "The C Programming Language".
> and while the Standard Library was not always consistently defined, the
> behavioral precedents for the language itself were very strongly established
> for implementations targeting machines that were architecturally like the
> PDP-11 (except for details of data formats and alignment). Compilers may
> offer *options* to waive certain behavioral expectations, but the fundamental
> core of the language that was popular treated things as defined. Further,
> the nature of "optimize from there" has changed quite fundamentally.
The nature of optimisation has changed hugely, as compilers have got
more sophisticated. If you want to go back to the days of limited
optimisations, you can do so - most compilers let you control those
features.
>
> It would not be astonishing, for example, for an optimizer to have integer
> overflow yield a result which differs from the correct result by some
> arbitrary multiple of (INT_MAX*2+2). On an 8086, the multiply instruction
> takes two 16-bit operands and always yields a 32-bit result in two specific
> registers. Given something like:
>
> long mul_add_l(unsigned char x, unsigned char y, long l)
> { return x*10000+y*7000+65536L; }
>
> the most efficient code would interpret the bottom 16 bits of one product
> as an unsigned number, but use all 32 bits of the other. While I would
> be surprised if any compilers of that era would actually find the most
> efficient code, I would not be in any way astonished if they did so, nor
> would I be astonished if a compiler added the lower 16 bits of the two
> products, sign-extended the result, and added that to l. If any result
> which is congruent to the correct result mod 65536 would be equally
> satisfactory, letting the compiler select among the calculation approaches
> would be a clear win for optimization. By contrast, writing the expression
> as "(unsigned)x*10000+(unsigned)y*7000+65536L;" would force the compiler
> to generate less-than-optimal code [and would also spend almost as many
> characters in the source text preventing the compiler from launching nuclear
> missiles as it spent doing useful work].
>
I can't figure out what you are trying to say here. I'll just assume
it's another one of your pathological examples designed specifically to
be undefined behaviour in some weird case, because you think a compiler
theoretically could used that to generate unexpected code.
It does not help when your example does not match your text (your
function makes no use of the parameter "l", which is a silly choice of
identifier).
>> If a particular compiler implemented something (with undefined behaviour
>> in the standards) in one way, and then changed how it implemented it,
>> then that is an issue between the compiler, its documentation, and its
>> users. If the compiler changed its documented behaviour, then that
>> could be a surprise to the user - but if the user has been relying on
>> undocumented behaviour, then they are at fault.
>
> Specifications for things generally won't bother promising not to do
> something unless the spec-writer can imagine someone thinking such a
> behavior was plausible. For example, if a future version of gcc were
> to generate nonsense machine code when a program uses type punning, even
> when using -fno-strict-aliasing, should the programmer be faulted for
> relying upon behavior that was never defined (gcc's documentation for
> -fno-strict-aliasing doesn't actually promise that pointer-based type
> punning will behave as though writing a pointer converts an object to a
> series of bytes, and reading a pointer interprets the underlying bytes
> as an object).
If the compiler documentation is imprecise, then it is the compiler
documentation that is at fault. In general, you can assume that the
compiler writers are trying to be as helpful as possible to their users
(I know /you/ like to assume they are evil spawns of Satan intent on
tricking unwary programmers - but the rest of us know they are trying to
help programmers generate efficient, correct code as easily as possible).
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-16 13:34 -0700 |
| Message-ID | <c9cb703c-db1b-4baa-9622-538aeaca5652@googlegroups.com> |
| In reply to | #93644 |
On Friday, September 16, 2016 at 12:59:14 PM UTC-5, David Brown wrote: > > That's popular myth #2. The term "Implementation-Defined" is only used > > in cases where *ALL* implementations are required to specify a precise > > behavior. It is not used in cases where 99% of implementations might be > > expected to define a specific behavior, but where it was deemed plausible > > that some implementations might not be able to. > > Making up numbers and claims does not help your argument. In what fraction of two's-complement implementations circa 1989 did left- shifting of a negative value do anything other than multiply by 2^N, shift the value bits left through the sign bit, or convert to unsigned, do the shift, and then convert to signed (note that on two's-complement implementations all three operations are equivalent). Unless the answer is greater than 1%, I would consider my 99% figure to be entirely accurate. > > As evidence, I offer the fact that shifting a negative number left is UB > > even though so far as I can tell every two's-complement machine (i.e. the > > majority of C implementations) implements them the same way. > > Left-shift of a negative number /is/ defined, as long as its value makes > sense. Perhaps you should read the standards before complaining about them. I did read the standard. From N1570 6.5.7: 4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros.... If E1 has a signed type and nonnegative value, and E1 x 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined. > The general rule for signed integers and their operations is that their > /value/ is significant, not their representation. Operations are > defined as long as the value makes sense. That would be logical on two's-complement machines, but it's not what the Standard actually says with regard to the left-shift operator. > -5 << 3 is defined to -5 * 2³, which is -40. It is only overflow of > signed integer shifts that is undefined behaviour. This is consistent > with all other arithmetic operations on signed integers. I would expect that some sign-magnitude implementations would have regarded -5<<3 as 40, and would not be particularly astonished to discover that some would trap (though I recall reading that an effort to find any such implementations came up empty). I would expect that some ones- complement implementations would interpret -5<<3 as -40, but that others might interpret it as -47 (-5 is 0xFFFA in ones'-complement; shifting that left with zero-fill would yield 0xFFD0, i.e. -47). While there are a few two's-complement implementations where treating a left shift of a negative value as defined behavior could sometimes cost an extra instruction, I'm unaware of any two's-complement implementation from the 1980s that didn't do so anyway. > Now, it would have been /possible/ for the C standards folks to say that > signed overflow was implementation dependent, not undefined behaviour. > However, they specifically choose undefined behaviour to give compiler > writers scope for optimisations - while also allowing compiler writers > to give defined behaviour if they wanted. If the Standard had made it Implementation-Defined behavior, that would have required all implementations to ensure that any operations that overflow always yield a fully-deterministic result. On some platforms that would have cost nothing, but on others it would have represented a significant expense. > And how does every two's complement machine implement left shifting of > negative numbers? As long as the result does not lead to overflow, they > will all do it in the same way - they will follow the C standards. If > it leads to overflow, then who knows what they will do - I certainly > would not assume it is consistent. Certainly the behaviour for when the > shift amount is too big (greater than or equal to the width of the type) > will vary from processor to processor, and perhaps vary depending on > whether the value is known at compile time or not. Nothing in the C Standard requires that two's-complement machines handle left-shift of negative numbers in that fashion, though I find it interesting that you criticize me for making a claim about 99% of implementations while you make a claim about 100%, notwithstanding the existence of hardware platforms where guaranteeing such behavior would have a non-zero cost in cases where a left-shift is followed by an operation that would require the carry flag to be clear. > The nature of optimisation has changed hugely, as compilers have got > more sophisticated. If you want to go back to the days of limited > optimisations, you can do so - most compilers let you control those > features. Unfortunately, compiler documentation often does a rather poor job of documenting what is or is not guaranteed when using particular flags. Further, the level of optimization that can make its way into a usable executable is not optimized by requiring that programmers ensure that programmers never give compilers any behavioral latitude, but rather by making it safe for programmers to give compilers considerable but not unlimited freedom. > If the compiler documentation is imprecise, then it is the compiler > documentation that is at fault. In general, you can assume that the > compiler writers are trying to be as helpful as possible to their users > (I know /you/ like to assume they are evil spawns of Satan intent on > tricking unwary programmers - but the rest of us know they are trying to > help programmers generate efficient, correct code as easily as possible). Which is more important in a quality compiler: 1. The efficiency of executable code it can generate when given a strictly- conforming source program. 2. The efficiency of executable code it can generate to perform a task given a source program which exploits features of the target architecture as well as compiler-specific features. 3. The efficiency of executable code it can generate to perform a task when given a source program which exploits features of the target architecture, but does not rely upon compiler-specific features that would be incompatible with other compilers for the same platform. 4. The ability to process code which relies upon behavioral precedents set by other implementations for similar targets, in a fashion consistent with those precedents. Today's compiler writers seem to regard #1 as their highest priority, and are far less interested in #4.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-16 16:23 -0700 |
| Message-ID | <lnk2ebzaxe.fsf@kst-u.example.com> |
| In reply to | #93663 |
supercat@casperkitty.com writes:
> On Friday, September 16, 2016 at 12:59:14 PM UTC-5, David Brown wrote:
[...]
>> supercat wrote:
>> > As evidence, I offer the fact that shifting a negative number left is UB
>> > even though so far as I can tell every two's-complement machine (i.e. the
>> > majority of C implementations) implements them the same way.
>>
>> Left-shift of a negative number /is/ defined, as long as its value makes
>> sense. Perhaps you should read the standards before complaining about them.
>
> I did read the standard. From N1570 6.5.7:
>
> 4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
> are filled with zeros.... If E1 has a signed type and nonnegative value,
> and E1 x 2E2 is representable in the result type, then that is the
> resulting value; otherwise, the behavior is undefined.
Right. Your statement was that "shifting a negative number
left is UB". It's UB only if the result is outside the range of
the signed type. Your statement implied (certainly to me, and
presumably to David) that left-shifting a negative number *always*
has undefined behavior. It doesn't.
If that's not what you meant, that's fine, but please recognize that
your statement was at best unclear.
[...]
--
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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-16 15:31 -0700 |
| Message-ID | <09cb4413-16a6-4b63-89d0-9dafe56562f6@googlegroups.com> |
| In reply to | #93669 |
On Friday, September 16, 2016 at 4:17:31 PM UTC-5, Keith Thompson wrote:
> supercat writes:
> > I did read the standard. From N1570 6.5.7:
> >
> > 4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
> > are filled with zeros.... If E1 has a signed type and nonnegative value,
> > and E1 x 2E2 is representable in the result type, then that is the
> > resulting value; otherwise, the behavior is undefined.
>
> Right. Your statement was that "shifting a negative number
> left is UB". It's UB only if the result is outside the range of
> the signed type. Your statement implied (certainly to me, and
> presumably to David) that left-shifting a negative number *always*
> has undefined behavior. It doesn't.
The language of the Standard only specifies behavior if E1 is unsigned, or
if *both* of the following conditions apply:
1. E1 is signed AND NON-NEGATIVE.
2. The result of multiplying E1 * 2^E2 would be representable in the
result type.
The expression -5 << 3 satisfies the second criterion, but fails the first.
Consequently, it invokes Undefined Behavior.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-16 19:06 -0700 |
| Message-ID | <lnfuozz3ea.fsf@kst-u.example.com> |
| In reply to | #93672 |
supercat@casperkitty.com writes:
> On Friday, September 16, 2016 at 4:17:31 PM UTC-5, Keith Thompson wrote:
>> supercat writes:
>> > I did read the standard. From N1570 6.5.7:
>> >
>> > 4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
>> > are filled with zeros.... If E1 has a signed type and nonnegative value,
>> > and E1 x 2E2 is representable in the result type, then that is the
>> > resulting value; otherwise, the behavior is undefined.
>>
>> Right. Your statement was that "shifting a negative number
>> left is UB". It's UB only if the result is outside the range of
>> the signed type. Your statement implied (certainly to me, and
>> presumably to David) that left-shifting a negative number *always*
>> has undefined behavior. It doesn't.
>
> The language of the Standard only specifies behavior if E1 is unsigned, or
> if *both* of the following conditions apply:
>
> 1. E1 is signed AND NON-NEGATIVE.
>
> 2. The result of multiplying E1 * 2^E2 would be representable in the
> result type.
>
> The expression -5 << 3 satisfies the second criterion, but fails the first.
> Consequently, it invokes Undefined Behavior.
You're absolutely right. Looks like I failed reading comprehension
for the day. My apologies.
--
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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-16 23:27 -0700 |
| Message-ID | <68e53f3a-5fcc-44fc-90c4-bcf8dc3db680@googlegroups.com> |
| In reply to | #93674 |
On Friday, September 16, 2016 at 6:59:15 PM UTC-5, Keith Thompson wrote:
> supercat writes:
> > The expression -5 << 3 satisfies the second criterion, but fails the first.
> > Consequently, it invokes Undefined Behavior.
>
> You're absolutely right. Looks like I failed reading comprehension
> for the day. My apologies.
Returning to my earlier point, which seems more plausible:
1. The authors of the Standard wanted to invite even two's-complement
implementations to behave nonsensically when left-shifting a negative
value unless he programmer explicitly cast the value to "unsigned"
first, or...
2. The authors of the Standard thought it so obvious that quality
two's-complement implementations should treat left-shifts of negative
values as a multiplication (at least in cases where the product
would be representable) that there was no need to waste ink saying
so.
Before you recognized that you'd misread the Standard, you presumably would
have thought that a programmer would be entitled to expect that when x==-5,
a compiler would evaluate x<<3 as -40 with no side-effects. Does the fact
that the Standard imposes no requirements change that?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-17 15:04 -0700 |
| Message-ID | <ln7faayyhf.fsf@kst-u.example.com> |
| In reply to | #93679 |
supercat@casperkitty.com writes:
> On Friday, September 16, 2016 at 6:59:15 PM UTC-5, Keith Thompson wrote:
>> supercat writes:
>> > The expression -5 << 3 satisfies the second criterion, but fails
>> > the first. Consequently, it invokes Undefined Behavior.
>>
>> You're absolutely right. Looks like I failed reading comprehension
>> for the day. My apologies.
>
> Returning to my earlier point, which seems more plausible:
>
> 1. The authors of the Standard wanted to invite even two's-complement
> implementations to behave nonsensically when left-shifting a negative
> value unless he programmer explicitly cast the value to "unsigned"
> first, or...
>
> 2. The authors of the Standard thought it so obvious that quality
> two's-complement implementations should treat left-shifts of negative
> values as a multiplication (at least in cases where the product
> would be representable) that there was no need to waste ink saying
> so.
3. The authors of the standard didn't want to impose requirements on
left shifts of negative numbers. The natural behavior for a given
system could naturally vary depending on the representation used
for signed integers. The authors either did not know whether some
implementations might behave in odd ways (such as a run-time trap),
or knew of implementations that do so. Shifts of negative values
are not particularly important anyway; imposing requirements on
their behavior could, on some systems, impose extra costs on shifts
of non-negative values, which are important.
I find it slightly odd that a left shift of a negative number has
undefined behavior, while a right shift of a negative number yields
an implementation-defined value. I presume there's a valid reason
for that.
> Before you recognized that you'd misread the Standard, you presumably would
> have thought that a programmer would be entitled to expect that when x==-5,
> a compiler would evaluate x<<3 as -40 with no side-effects. Does the fact
> that the Standard imposes no requirements change that?
Certainly. On more careful reading, the standard talks about
shifting bits, not values. That's unambiguous for unsigned types
and for non-negative values of signed types, but representations for
negative values of signed types can vary, so it's not immediately
clear what shifting bits even means. I could, I suppose, think
about how it should work for the three permitted representations
(I haven't taken the time to do so), but that wouldn't say much
about how the shift instructions of real-world CPUs actually behave.
And prior to C99, the standard didn't even restrict the possible
representations for signed types to the three choices we have now.
(Perhaps it's time for the next edition of the C standard to mandate
2's-complement and tighten up some of the requirements, but I think
that's a separate discussion. The current standard has to cater
to the three possible representations -- and represention doesn't
imply a particular behavior.)
I don't even use shift operators on signed types; as far as I'm
concerned they only make sense for unsigned types. The fact that
they're well defined for non-negative signed values that don't
overflow is just a (small) bonus. YMMV.
If I have a possibly negative signed value and I want to multiply
it by 8, I just multiply it by 8. If the compiler can implement
that as a shift instruction, that's fine with me. If it can't,
that's fine with me too.
I just experimented with several compilers and found that
-5 << 3 == -40
I find this mildly interesting, but not particularly useful.
--
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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-17 20:35 -0700 |
| Message-ID | <e52a2d87-580e-4223-a258-3a002f972757@googlegroups.com> |
| In reply to | #93689 |
On Saturday, September 17, 2016 at 2:50:35 PM UTC-5, Keith Thompson wrote: > 3. The authors of the standard didn't want to impose requirements on > left shifts of negative numbers. The natural behavior for a given > system could naturally vary depending on the representation used > for signed integers. The authors either did not know whether some > implementations might behave in odd ways (such as a run-time trap), > or knew of implementations that do so. Shifts of negative values > are not particularly important anyway; imposing requirements on > their behavior could, on some systems, impose extra costs on shifts > of non-negative values, which are important. There are at least two different sensible behaviors for ones'-complement systems, and at least three different sensible behaviors for sign-magnitude systems. Mandating a particular behavior from such systems would almost certainly have broken some code that relied upon its system using the "other" behavior. There is only one sensible behavior for two's-complement systems. > I find it slightly odd that a left shift of a negative number has > undefined behavior, while a right shift of a negative number yields > an implementation-defined value. I presume there's a valid reason > for that. On a sign-magnitude system, a left-shift of a negative number might plausibly be trapped as an overflow condition, since the sign bit would likely get flipped [trapping is one of the three plausible behaviors on such systems]. I don't think any sign-magnitude systems *actually* trap in that case, but it would be a sensible behavior. > > Before you recognized that you'd misread the Standard, you presumably would > > have thought that a programmer would be entitled to expect that when x==-5, > > a compiler would evaluate x<<3 as -40 with no side-effects. Does the fact > > that the Standard imposes no requirements change that? > > Certainly. On more careful reading, the standard talks about > shifting bits, not values. That's unambiguous for unsigned types > and for non-negative values of signed types, but representations for > negative values of signed types can vary, so it's not immediately > clear what shifting bits even means. Is the number of conforming, non-two's-complement, implementations of C99 greater than zero? So far as I can tell, there is no reason to expect that any practical conforming implementation of any future standard will ever use anything other than two's-complement as its primary integer representation. If one regards two's-complement mathematically as being performed by sign-extending to an infinite-precision type, performing the operation on those values, and then regarding the result as defined if and only if the top bit of the result type matches all the bits to its left, there is no ambiguity whatsoever as to what a left-shift means. > I could, I suppose, think > about how it should work for the three permitted representations > (I haven't taken the time to do so), but that wouldn't say much > about how the shift instructions of real-world CPUs actually behave. > And prior to C99, the standard didn't even restrict the possible > representations for signed types to the three choices we have now. While might not make much sense to define the behavior on a hypothetical sign-magnitude machine, that shouldn't prevent programmers from being able to use it on machines that actually exist. > (Perhaps it's time for the next edition of the C standard to mandate > 2's-complement and tighten up some of the requirements, but I think > that's a separate discussion. The current standard has to cater > to the three possible representations -- and represention doesn't > imply a particular behavior.) The proper thing to do would be to recognize that implementations other than two's-complement are not "normal", and require that such implementations define macros to indicate their deviations from typical behaviors. At the same time, it may be useful to allow implementations to use integer forms beyond the indicated three provided they document such behavior. If a 32-bit platform treated 0x80000000 as a NaN, that could be useful (providing the benefits of overflow trapping but at a much lower cost) but extending the concept to 64 bits would be expensive *unless* it were allowed to define INT_MIN as -0x7FFFFFFF00000000 rather than -0x7FFFFFFFFFFFFFFF-1]. At present, however, the Standard would not allow such behavior, thus making support for such behavior impractical with multi-precision math. > I don't even use shift operators on signed types; as far as I'm > concerned they only make sense for unsigned types. The fact that > they're well defined for non-negative signed values that don't > overflow is just a (small) bonus. YMMV. How would you multiply a signed number by 2^N in such a fashion as to yield defined behavior in all cases where the result would be representable, without relying upon implementation-defined behavior? While casting to unsigned would yield working code on sane implementations, it does not describe the actual intention of the code nearly as well as a simple left shift. Note also that x*(1<<y) will fail for -1<<31, and -(x*(-1<<y)) will fail for (-2147483647-1)<<0. > If I have a possibly negative signed value and I want to multiply > it by 8, I just multiply it by 8. If the compiler can implement > that as a shift instruction, that's fine with me. If it can't, > that's fine with me too. Some applications use variable powers of two. While many compilers would be likely to simplify x*(1<<y) as x<<y, the former will invoke UB in cases where the latter would not, and the former will also avoid the need to ensure that code uses the properly-sized constant 1. Note that using a long long constant when x is 32 bits will force many compiler to generate less efficient code than they could with an "int" constant, since invoking expression x*(1LL<<y) with y==32 would result in an implementation-defined conversion from "long long" to "int", but on e.g. x86 platforms the simplest code for x<<y would yield x when y is 32. > I just experimented with several compilers and found that > -5 << 3 == -40 > I find this mildly interesting, but not particularly useful. Since -5 is ...11111111011 and since ...11111111011000 is -40, that should hardly be surprising.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-18 00:09 -0700 |
| Message-ID | <30fd7c5b-3a62-4eb1-b123-d0e44bc31095@googlegroups.com> |
| In reply to | #93721 |
On Sunday, September 18, 2016 at 4:35:32 AM UTC+1, supe...@casperkitty.com wrote: > > Is the number of conforming, non-two's-complement, implementations of C99 > greater than zero? So far as I can tell, there is no reason to expect > that any practical conforming implementation of any future standard will > ever use anything other than two's-complement as its primary integer > representation. > Here's an idea for you. Data consists of reals, integers, strings and "connections" or graph edges, which in programming we represent by addresses. Most other data is made up of combinations of those four elements (I don't know if anyone can provide a good counterexample of data that isn't well so-described). Now modern machines operate on 64 bits. But we seldom if ever need all 64 bits. So why not "steal" a bit or two to tag each 64 bit value with its type? Then we've got two advantages, fast machine-level operational validity checking, and the ability to tighten up high level languages. But of course our integers now look like this: integer tag No-one will ever use these bits Data (big negative number) / / / 01 111111 11111111 11011110 10101011 00000111 11110000 10110111 00000001
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-18 19:36 +0100 |
| Message-ID | <87poo1jbr9.fsf@bsb.me.uk> |
| In reply to | #93725 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > On Sunday, September 18, 2016 at 4:35:32 AM UTC+1, supe...@casperkitty.com wrote: >> >> Is the number of conforming, non-two's-complement, implementations of C99 >> greater than zero? So far as I can tell, there is no reason to expect >> that any practical conforming implementation of any future standard will >> ever use anything other than two's-complement as its primary integer >> representation. >> > Here's an idea for you. > Data consists of reals, integers, strings and "connections" or graph edges, > which in programming we represent by addresses. Most other data is > made up of combinations of those four elements (I don't know if anyone > can provide a good counterexample of data that isn't well > so-described). Functions? Types? And since, presumably, "array of" is one on the combining operators, I'm not sure why you pick strings as being basic. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-18 15:29 -0700 |
| Message-ID | <a0375a36-418d-4147-8bd8-d9c58bb5ca1d@googlegroups.com> |
| In reply to | #93744 |
On Sunday, September 18, 2016 at 7:36:50 PM UTC+1, Ben Bacarisse wrote: > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > > > > Data consists of reals, integers, strings and "connections" or > > graph edges, which in programming we represent by addresses. > > Most other data is made up of combinations of those four elements > > (I don't know if anyone can provide a good counterexample of > > data that isn't well so-described). > > Functions? Types? And since, presumably, "array of" is one on the > combining operators, I'm not sure why you pick strings as being basic. > A function is of course data to an interpreter or a compiler. Some languages allow functions to be treated as data objects and passed about. Generally however you make a distinction between functions and data. If you do genuinely operate on a function, as opposed to doing dynamic run-time binding, you represent it somehow, normally as a graph. That will be how Mathematica and Maple are built. You can say that everything is atomically an array of bytes, or even of bits. The question what do the bits mean. If we have the string "Fred" we can say that the first byte means "the English letter F", and that's useful. But you'll seldom get the data in that way. No one-says, what's the first letter of your name? The second. People, do say, "Fred, what's your age?", "your payroll id?" and so on - these are the "fields". Then actually "character" is a bit of an Anglo-centric concept, "word" isn't. Virtually every language has a concept of the "word", only ones ultimately influenced by the Phoenician people have a concept of "letter". Words are better thought of as a basic unit of language than characters.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-19 01:20 +0100 |
| Message-ID | <878tuokaes.fsf@bsb.me.uk> |
| In reply to | #93763 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > On Sunday, September 18, 2016 at 7:36:50 PM UTC+1, Ben Bacarisse wrote: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> >> >> > Data consists of reals, integers, strings and "connections" or >> > graph edges, which in programming we represent by addresses. >> > Most other data is made up of combinations of those four elements >> > (I don't know if anyone can provide a good counterexample of >> > data that isn't well so-described). >> >> Functions? Types? And since, presumably, "array of" is one on the >> combining operators, I'm not sure why you pick strings as being basic. >> > A function is of course data to an interpreter or a compiler. Obviously I meant as data in ordinary programs. > Some > languages allow functions to be treated as data objects and passed > about. And operated on and computed with. > Generally however you make a distinction between functions > and data. If you do genuinely operate on a function, as opposed to > doing dynamic run-time binding, you represent it somehow, normally > as a graph. That will be how Mathematica and Maple are built. Ah, so if Mathematica represents integers or strings as lists, you will remove them from your definition of basic data? > You can say that everything is atomically an array of bytes, or > even of bits. The question what do the bits mean. Exactly. You've chosen a level of interpretation and nothing will shift you from it. But, other interpretations are also possible. One of the most useful is the model of computation provided by a programming language. I prefer that one to drawing a line somewhere just above the bits and saying "that's what data types are". <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-18 09:48 -0700 |
| Message-ID | <lna8f5xigd.fsf@kst-u.example.com> |
| In reply to | #93721 |
supercat@casperkitty.com writes:
> On Saturday, September 17, 2016 at 2:50:35 PM UTC-5, Keith Thompson wrote:
[...]
>> (Perhaps it's time for the next edition of the C standard to mandate
>> 2's-complement and tighten up some of the requirements, but I think
>> that's a separate discussion. The current standard has to cater
>> to the three possible representations -- and represention doesn't
>> imply a particular behavior.)
>
> The proper thing to do would be to recognize that implementations
> other than two's-complement are not "normal", and require that such
> implementations define macros to indicate their deviations from typical
> behaviors.
Too complicated. If non-two's-complement systems are really obsolete,
why not just have the next C standard require two's-complement? If
there are any remaining one's-complement or sign-and-magnitude systems,
let them claim conformance to the old C11 standard, or just let them be
non-conforming.
That's assuming we can make that assumption. It's likely that there's
no good reason to use anything other than two's-complement, but I'm not
100% confident that that will never change. This requires input from
people who know more about this stuff than I do.
And of course two's-complement representation doesn't necessarily imply
the usual two's complement behavior in all cases; it tells us how
negative integers are represented, but it doesn't tell us the result of
evaluating INT_MAX+1 or -5<<3. That's another set of assumptions that
might or might not be sensible to make in a hypothetical new standard.
> At the same time, it may be useful to allow implementations
> to use integer forms beyond the indicated three provided they document
> such behavior. If a 32-bit platform treated 0x80000000 as a NaN, that
> could be useful (providing the benefits of overflow trapping but at a
> much lower cost) but extending the concept to 64 bits would be expensive
> *unless* it were allowed to define INT_MIN as -0x7FFFFFFF00000000 rather
> than -0x7FFFFFFFFFFFFFFF-1]. At present, however, the Standard would not
> allow such behavior, thus making support for such behavior impractical
> with multi-precision math.
C already explicitly allows the two's-complement representation with
sign bit 1 and all value bits 0 to be a trap representation. As for
-0x7FFFFFFF00000000, I'm skeptical that any such systems exist or are
worth considering.
>> I don't even use shift operators on signed types; as far as I'm
>> concerned they only make sense for unsigned types. The fact that
>> they're well defined for non-negative signed values that don't
>> overflow is just a (small) bonus. YMMV.
>
> How would you multiply a signed number by 2^N in such a fashion as to
> yield defined behavior in all cases where the result would be
> representable, without relying upon implementation-defined behavior?
I'd probably use the "*" operator, for example -5 * (1<<3).
[...]
--
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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-18 19:38 +0200 |
| Message-ID | <nrmjdv$j4t$1@dont-email.me> |
| In reply to | #93732 |
On 18/09/16 18:48, Keith Thompson wrote: > supercat@casperkitty.com writes: >> On Saturday, September 17, 2016 at 2:50:35 PM UTC-5, Keith Thompson wrote: > [...] >>> (Perhaps it's time for the next edition of the C standard to mandate >>> 2's-complement and tighten up some of the requirements, but I think >>> that's a separate discussion. The current standard has to cater >>> to the three possible representations -- and represention doesn't >>> imply a particular behavior.) >> >> The proper thing to do would be to recognize that implementations >> other than two's-complement are not "normal", and require that such >> implementations define macros to indicate their deviations from typical >> behaviors. > > Too complicated. If non-two's-complement systems are really obsolete, > why not just have the next C standard require two's-complement? If > there are any remaining one's-complement or sign-and-magnitude systems, > let them claim conformance to the old C11 standard, or just let them be > non-conforming. That would have my vote. (But I would not want signed integer overflow to be defined behaviour.) Drop padding bits in types too, any character sets that don't match ASCII for the first 128 characters, CHAR_BIT that is not 8, 16 or 32, and int sizes that are not 16 or 32 bits. I'm sure there are a good many other things that are implementation defined that could be fixed, or at least more limited, without affecting any systems that would be likely to support C20 (or whatever the next standard becomes). It might not affect much code, but it could simplify the standards document - and that would be great! > > That's assuming we can make that assumption. It's likely that there's > no good reason to use anything other than two's-complement, but I'm not > 100% confident that that will never change. This requires input from > people who know more about this stuff than I do. From the point of view of hardware and the gate-level implementation of a cpu, there is no good reason to use anything other than two's complement. Long ago, you could argue that signed magnitude forms were more efficient if you did a lot of multiplication or division, or in combination with BCD for making numbers that are easily converted to human-readable format. These are not issues for modern systems. (But while I know more about gate-level implementation of ALUs than most people, I don't know /everything/ here - presumably the C standards people would ask many others before making such decisions.)
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-18 15:33 -0700 |
| Message-ID | <ln60psyh1n.fsf@kst-u.example.com> |
| In reply to | #93743 |
David Brown <david.brown@hesbynett.no> writes:
> On 18/09/16 18:48, Keith Thompson wrote:
>> supercat@casperkitty.com writes:
>>> On Saturday, September 17, 2016 at 2:50:35 PM UTC-5, Keith Thompson wrote:
>> [...]
>>>> (Perhaps it's time for the next edition of the C standard to mandate
>>>> 2's-complement and tighten up some of the requirements, but I think
>>>> that's a separate discussion. The current standard has to cater
>>>> to the three possible representations -- and represention doesn't
>>>> imply a particular behavior.)
>>>
>>> The proper thing to do would be to recognize that implementations
>>> other than two's-complement are not "normal", and require that such
>>> implementations define macros to indicate their deviations from typical
>>> behaviors.
>>
>> Too complicated. If non-two's-complement systems are really obsolete,
>> why not just have the next C standard require two's-complement? If
>> there are any remaining one's-complement or sign-and-magnitude systems,
>> let them claim conformance to the old C11 standard, or just let them be
>> non-conforming.
>
> That would have my vote. (But I would not want signed integer overflow
> to be defined behaviour.) Drop padding bits in types too, any character
> sets that don't match ASCII for the first 128 characters,
Padding bits might still be sensible in some cases. For example, there
have been systems in the past, presumably optimized for floating-point,
that represent integers as floating-point numbers with the exponent
fixed at zero (or something like that). It's worth asking whether we
can drop the idea of padding bits, but I'm not ready to assume that we
can do so.
> CHAR_BIT that
> is not 8, 16 or 32, and int sizes that are not 16 or 32 bits.
64-bit int is perfectly sensible for 64-bit systems. The main
reason, I think, that it's not more common is that it leaves a
gap; if you have 8-bit char and 64-int, and short is the only type
in between, then you can't have both 16-bit and 32-bit integers.
Extended integer types, appropriate typedefs in <stdint.h>, should
solve that, but I don't think any implementations have taken
advantage of that (probably because of backward compatibility).
[...]
--
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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-18 13:58 -0700 |
| Message-ID | <1bd8192c-467d-4f88-b479-e68a410bde8a@googlegroups.com> |
| In reply to | #93754 |
On Sunday, September 18, 2016 at 3:10:56 PM UTC-5, Keith Thompson wrote: > David Brown writes: > > That would have my vote. (But I would not want signed integer overflow > > to be defined behaviour.) Drop padding bits in types too, any character > > sets that don't match ASCII for the first 128 characters, > > Padding bits might still be sensible in some cases. For example, there > have been systems in the past, presumably optimized for floating-point, > that represent integers as floating-point numbers with the exponent > fixed at zero (or something like that). It's worth asking whether we > can drop the idea of padding bits, but I'm not ready to assume that we > can do so. There are many tasks where padding bits would be a non-issue, but there are others that can be performed more efficiently on systems which don't use padding bits. There's no reason systems with padding bits should not be able to perform in defined fashion those tasks for which they would impose no impediment, but there is also no reason why tasks that could benefit from a guaranteed lack of padding bits should not be performed efficiently on padding-free systems.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-18 14:15 -0700 |
| Message-ID | <3a97d60b-b3f1-4a89-be61-e54fa6a33b3d@googlegroups.com> |
| In reply to | #93754 |
On Sunday, September 18, 2016 at 3:10:56 PM UTC-5, Keith Thompson wrote: > 64-bit int is perfectly sensible for 64-bit systems. The main > reason, I think, that it's not more common is that it leaves a > gap; if you have 8-bit char and 64-int, and short is the only type > in between, then you can't have both 16-bit and 32-bit integers. > Extended integer types, appropriate typedefs in <stdint.h>, should > solve that, but I don't think any implementations have taken > advantage of that (probably because of backward compatibility). The most efficient behavior on many 64-bit systems would be to apply the type "int" to 32-bit storage locations whose address is exposed to outside code, but allow a compiler to substitute 64-bit variables when it sees fit. As written, however, the Standard wouldn't allow that (even if some variables were declared as int_least64_t, the implementation would be required to pick the same size for all of them and document that choice). There is a fair amount of code that expects that computations on a uint32_t will wrap mod 4294967296, and making "int" larger than 32 bits will break such code. The remedy I'd like to see would be for the Standard to define fixed-sized types which have wrapping semantics independent of the size of "int" in all cases where code compiles; had such types been added in C99 or C11, porting 32-bit code to 64 bits would be a lot easier.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-18 23:15 +0100 |
| Message-ID | <nrn3l3$f9d$1@dont-email.me> |
| In reply to | #93754 |
On 18/09/2016 23:33, Keith Thompson wrote: >> is not 8, 16 or 32, and int sizes that are not 16 or 32 bits. > > 64-bit int is perfectly sensible for 64-bit systems. The main > reason, I think, that it's not more common is that it leaves a > gap; if you have 8-bit char and 64-int, and short is the only type > in between, then you can't have both 16-bit and 32-bit integers. > Extended integer types, appropriate typedefs in <stdint.h>, should > solve that, but I don't think any implementations have taken > advantage of that (probably because of backward compatibility). Short short? 'short' and 'long' might have been better implemented as relative (not absolute) modifiers of 'int': respectively halving or doubling the width, whatever that is, rather than allowing them to do nothing at the whim of the implementation. With 'short short' allowed, and either raising an error, or capping the result /because it can't go any further/, when a lower or upper width limit is reached. Eg: Standard int: 16 32 64 char 8 8 8 short short int 8/? 8/? 16 short int 8/? 16 32 int 16 32 64 long int 32 64 64/128/? long long int 32 64/128/? 64/256/? And, perhaps, the possibility of allowing the standard int width to be set. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-18 15:46 -0700 |
| Message-ID | <46fcfdac-a18e-4ee4-8f57-33fd9bce02cd@googlegroups.com> |
| In reply to | #93762 |
On Sunday, September 18, 2016 at 5:15:14 PM UTC-5, Bart wrote: > 'short' and 'long' might have been better implemented as relative (not > absolute) modifiers of 'int': respectively halving or doubling the > width, whatever that is, rather than allowing them to do nothing at the > whim of the implementation. For a long time, the majority of C implementations defined integer types consistently as: char 8 bits short 16 bits int 16 or 32 bits long 32 bits I don't see how making the sizes relative would be an improvement on that. It would be more useful to define a means by which a piece of source code could indicate its expectations for integer types, with a requirement that compilers must either process the code in accordance with its specifications or indicate in a defined fashion that it cannot do so. If a program indicates that it needs integer overflow to behave a certain way, then within that program integer overflow would not cause Undefined Behavior. Such a spec would likely prevent the program from being compiled on some implementations, but having a program runs correctly on 10% of implementations and be refused by 90% would be better than having it run correctly, 100% of the time, on 99% of implementations, and run correctly 99% of the time on the remaining 1%.
[toc] | [prev] | [next] | [standalone]
Page 2 of 9 — ← Prev page 1 [2] 3 4 5 6 7 8 9 Next page →
Back to top | Article view | comp.lang.c
csiph-web