Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #108589 > unrolled thread
| Started by | joel.rees@gmail.com |
|---|---|
| First post | 2017-04-27 03:13 -0700 |
| Last post | 2017-04-30 22:05 -0700 |
| Articles | 20 on this page of 127 — 21 participants |
Back to article view | Back to comp.lang.c
Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 03:13 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 03:41 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-27 11:59 +0100
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 14:35 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-27 15:13 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 00:58 +0200
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-27 16:44 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 20:04 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 08:53 +0200
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 08:23 -0700
Re: Is this code considered to transgress the signed overflow purism? Manfred <noname@invalid.add> - 2017-04-28 18:05 +0200
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-28 09:22 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-28 12:24 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 00:03 +0100
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 16:37 -0700
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-28 17:09 -0700
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 17:34 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 01:43 +0100
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-28 21:21 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-29 02:04 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 11:46 +0100
Re: Is this code considered to transgress the signed overflow purism? Robert Wessel <robertwessel2@yahoo.com> - 2017-04-30 12:05 -0500
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 11:33 +0100
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-29 08:26 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-29 17:58 +0200
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-29 09:13 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-30 12:55 +0200
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-30 09:17 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-30 20:35 +0200
Re: Is this code considered to transgress the signed overflow purism? David Kleinecke <dkleinecke@gmail.com> - 2017-04-30 15:39 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-05-01 16:21 +0200
Re: Is this code considered to transgress the signed overflow purism? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2017-05-02 06:35 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-05-02 16:29 +0200
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 20:58 +0100
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 18:43 +0200
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-28 14:09 +0100
Re: Is this code considered to transgress the signed overflow purism? scott@slp53.sl.home (Scott Lurndal) - 2017-04-28 14:23 +0000
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-28 16:17 +0100
Re: Is this code considered to transgress the signed overflow purism? scott@slp53.sl.home (Scott Lurndal) - 2017-04-28 15:55 +0000
Re: Is this code considered to transgress the signed overflow purism? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2017-04-28 19:11 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 11:23 +0100
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-29 11:31 +0100
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 12:01 +0100
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-29 12:47 +0100
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-29 15:20 +0200
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-29 15:22 +0100
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-29 16:52 +0200
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-29 15:18 +0100
Re: Is this code considered to transgress the signed overflow purism? Jean-Marc Bourguet <jm@bourguet.org> - 2017-04-29 14:25 +0200
Re: Is this code considered to transgress the signed overflow purism? Jerry Stuckle <jstucklex@attglobal.net> - 2017-04-29 08:05 -0400
Re: Is this code considered to transgress the signed overflow purism? Gareth Owen <gwowen@gmail.com> - 2017-04-29 13:34 +0100
Re: Is this code considered to transgress the signed overflow purism? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2017-04-29 05:55 -0700
Re: Is this code considered to transgress the signed overflow purism? GOTHIER Nathan <nathan.gothier@gmail.com> - 2017-04-29 15:11 +0200
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-29 15:24 +0200
Re: Is this code considered to transgress the signed overflow purism? Gareth Owen <gwowen@gmail.com> - 2017-04-29 14:57 +0100
Re: Is this code considered to transgress the signed overflow purism? asetofsymbols@gmail.com - 2017-05-03 12:17 -0700
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-05-03 16:36 -0700
Re: Is this code considered to transgress the signed overflow purism? asetofsymbols@gmail.com - 2017-05-03 11:26 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-05-03 21:40 +0200
Re: Is this code considered to transgress the signed overflow purism? asetofsymbols@gmail.com - 2017-05-03 23:46 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-28 08:55 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 20:20 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 20:26 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 10:19 +0200
Re: Is this code considered to transgress the signed overflow purism? James Kuyper <jameskuyper@verizon.net> - 2017-04-28 09:57 -0400
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 17:06 +0200
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 08:38 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 18:51 +0200
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-29 12:43 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 14:02 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-30 14:25 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 15:01 -0700
Re: Is this code considered to transgress the signed overflow purism? James Kuyper <jameskuyper@verizon.net> - 2017-04-28 09:48 -0400
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 08:07 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 18:56 +0200
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-28 11:30 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-28 08:35 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 00:54 +0200
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-27 21:05 -0700
Re: Is this code considered to transgress the signed overflow purism? David Brown <david.brown@hesbynett.no> - 2017-04-28 10:58 +0200
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-28 10:50 +0100
Re: Is this code considered to transgress the signed overflow purism? James Kuyper <jameskuyper@verizon.net> - 2017-04-28 10:01 -0400
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-05-02 05:06 -0700
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-28 23:57 +0100
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 12:28 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-30 12:41 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-04-30 21:46 +0100
Re: Is this code considered to transgress the signed overflow purism? Thiago Adams <thiago.adams@gmail.com> - 2017-05-01 05:41 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-05-01 13:57 +0100
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-05-02 05:30 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-05-02 16:13 +0100
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-05-02 09:12 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-05-02 18:15 +0100
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-05-02 11:26 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-05-02 21:39 +0100
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-05-02 13:53 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-05-02 14:10 -0700
Re: Is this code considered to transgress the signed overflow purism? bartc <bc@freeuk.com> - 2017-05-02 22:36 +0100
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-05-02 15:27 -0700
Re: Is this code considered to transgress the signed overflow purism? Robert Wessel <robertwessel2@yahoo.com> - 2017-05-03 00:45 -0500
Re: Is this code considered to transgress the signed overflow purism? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-05-03 11:57 +0100
Re: Is this code considered to transgress the signed overflow purism? Robert Wessel <robertwessel2@yahoo.com> - 2017-05-03 13:34 -0500
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-05-03 12:05 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-05-05 02:58 -0700
Re: Is this code considered to transgress the signed overflow purism? Thiago Adams <thiago.adams@gmail.com> - 2017-05-03 05:26 -0700
Re: Is this code considered to transgress the signed overflow purism? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2017-05-03 05:54 -0700
Re: Is this code considered to transgress the signed overflow purism? Thiago Adams <thiago.adams@gmail.com> - 2017-05-03 06:49 -0700
Re: Is this code considered to transgress the signed overflow purism? Thiago Adams <thiago.adams@gmail.com> - 2017-05-03 06:51 -0700
Re: Is this code considered to transgress the signed overflow purism? jadill33@gmail.com - 2017-05-03 09:03 -0700
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-05-02 14:47 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-05-03 17:45 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 14:42 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-30 23:57 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-05-02 04:32 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-05-03 18:20 -0700
Re: Is this code considered to transgress the signed overflow purism? luser droog <luser.droog@gmail.com> - 2017-05-08 23:12 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-05-09 19:54 -0700
Re: Is this code considered to transgress the signed overflow purism? luser droog <luser.droog@gmail.com> - 2017-05-09 21:21 -0700
Re: Is this code considered to transgress the signed overflow purism? James Kuyper <jameskuyper@verizon.net> - 2017-04-27 10:46 -0400
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-27 08:37 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-27 09:38 -0700
Re: Is this code considered to transgress the signed overflow purism? supercat@casperkitty.com - 2017-04-27 10:17 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-27 12:10 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 13:50 -0700
Re: Is this code considered to transgress the signed overflow purism? Keith Thompson <kst-u@mib.org> - 2017-04-30 14:11 -0700
Re: Is this code considered to transgress the signed overflow purism? Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-30 14:44 -0700
Re: Is this code considered to transgress the signed overflow purism? joel.rees@gmail.com - 2017-04-30 22:05 -0700
Page 4 of 7 — ← Prev page 1 2 3 [4] 5 6 7 Next page →
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-28 08:55 -0700 |
| Message-ID | <lno9vgle75.fsf@kst-u.example.com> |
| In reply to | #108651 |
bartc <bc@freeuk.com> writes:
> On 28/04/2017 00:44, Keith Thompson wrote:
[...]
>> It can be tempting to use "<<" as a replacement for multiplying by
>> a power of 2. For example, one might write `n << 3` rather than
>> `n * 8`. But it's UB if n is negative -- and it's usually better
>> to write `n * 8` and let the compiler figure out whether it makes
>> sense to use a shift instruction.
>
> With gcc (on my x86 machine), it uses left shift to multiply a signed
> int by 8, one that it doesn't know whether it's negative or not.
>
> It knows that left-shifting a negative int will work. I think it will
> always work on two's complement (ie. give the same result as multiply),
> and many will spend their entire working lives working with such
> machines. Yet they are not allowed to assume that. Ever.
You're allowed to assume anything you like -- but you should be aware
that your assumptions might not be universally valid, even if your CPU
uses 2's-complement.
> As for UB on left-shifting 3 places, isn't this the same UB you get when
> multiplying by 8 and the result might overflow? In that case it doesn't
> seem to matter which is used.
No. (-3 * 8) is well defined. (-3 << 8) has undefined behavior.
> (BTW why didn't the language just prohibit shifts on signed values if it
> frowns upon them so much?)
Shifts on *non-negative* signed values are well defined as long as the
result is representable in the type. Prohibiting shifts on signed
values would make (1 << 3) invalid (you'd have to write (1U << 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 | joel.rees@gmail.com |
|---|---|
| Date | 2017-04-27 20:20 -0700 |
| Message-ID | <6175390e-9ea6-45f9-bf8c-d87525c332da@googlegroups.com> |
| In reply to | #108630 |
On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote: > joel rees@somewhere writes: > [...] > > We have this coddling of brain-damaged CPUs when a left-shift on a > > negative operand is specified on sign-magnitude architectures or > > something, but we have this assurance that casting a -1 to an unsigned > > fills the thing with ones. > > > > (I know calling it brain-damaged is too extreme, but ...) > > I suggest you might benefit from describing these things in less > inflammatory terms. Not sure how. > The behavor of left-shifting a negative value is undefined. Without context, I suppose it is. But mapping it to a logical shift left on the CPU, whatever the CPU gives for that, seems reasonable to me. Far more reasonable than assuming that casting a minus one to an unsigned type should always result in a bit mask of the type's width. > This is specified in N1570 6.5.7p4. > > (I don't recall that I've ever felt the need to left-shift a negative > integer.) Have you even left-shifted an unsigned char expecting specifically for the upper bits to disappear, instead of pulling the unsigned char into and unsigned long to do the shift and then masking the upper bits back out with a cast back to unsigned char? And hoping the compiler (which often misses such optimizations) will optimize out your excessive code on CPUs that will allocate a double short register to do the long shift? > The behavior of converting an integer (either signed or unsigned) value > to an unsigned type is well defined; the result is adjusted modulo > MAX+1, where MAX is the maximum value of the unsigned type. This is > described in N1570 6.3.1.3p2. > > (N1570 is the latest publicly available draft of the ISO C standard, > available at http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf .) > > [...] > > > Unsigned char promoted to signed int? > > Yes. The promotion rules are in N1570 6.3.1.1p2. The idea is that > there are no arithmetic operations on types narrower than int or > unsigned int, so anything narrower must be "promoted" before you can > operate on it. > > If an int can represent all values of the original type (as > restricted by the width, for a bit-field), the value is converted to > an int; otherwise, it is converted to an unsigned int. These are > called the *integer promotions*. > > The 1989 ANSI C committee had to choose between two schemes, both > implemented by existing compilers at the time: "unsigned preserving" and > "value preserving". They chose the latter. (I think I would have > preferred unsigned preserving semantics myself, but I haven't taken the > time to think about possible disadvantages.) This is discussed in the > C99 Rationale, section 6.3.1.1, available at > http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf . If I had the time, I'd go read it. I'm sure they thought they had a good reason. I'll still push for splitting the standard if anyone is willing to discuss it. Embedded has drastically different needs than desktop or server, and I even think desktop and server might be well served by fine-tuning the standard to the target. -- Joel Rees "Is the standard made for man? Or is man made for the standard?" "Grasshopper. Go bother some other guru for a while."
[toc] | [prev] | [next] | [standalone]
| From | joel.rees@gmail.com |
|---|---|
| Date | 2017-04-27 20:26 -0700 |
| Message-ID | <ad75f0dc-52ba-45b6-8918-898172a8a386@googlegroups.com> |
| In reply to | #108641 |
(erk) On Friday, April 28, 2017 at 12:20:18 PM UTC+9, joel...@somewhere wrote: > On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote: > [...] > Have you even left-shifted an unsigned char expecting specifically erm, "ever" (my bad. Sorry.) > for the upper bits to disappear, instead of pulling the unsigned > char into and unsigned long to do the shift and then masking the > upper bits back out with a cast back to unsigned char? > [...] > > -- > Joel Rees > > "Is the standard made for man? Or is man made for the standard?" > > "Grasshopper. Go bother some other guru for a while."
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-28 10:19 +0200 |
| Message-ID | <odutnq$8kf$1@dont-email.me> |
| In reply to | #108641 |
On 28/04/17 05:20, joel.rees@gmail.com wrote: > On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote: >> joel rees@somewhere writes: [...] >>> We have this coddling of brain-damaged CPUs when a left-shift on >>> a negative operand is specified on sign-magnitude architectures >>> or something, but we have this assurance that casting a -1 to an >>> unsigned fills the thing with ones. >>> >>> (I know calling it brain-damaged is too extreme, but ...) >> >> I suggest you might benefit from describing these things in less >> inflammatory terms. > > Not sure how. > >> The behavor of left-shifting a negative value is undefined. > > Without context, I suppose it is. The context here is C programming unless explicitly stated otherwise, and in that context left-shifting a negative value is undefined. > > But mapping it to a logical shift left on the CPU, whatever the CPU > gives for that, seems reasonable to me. Logical shifts work naturally on /unsigned/ types. > > Far more reasonable than assuming that casting a minus one to an > unsigned type should always result in a bit mask of the type's > width. That is perfectly reasonable for modulo arithmetic on unsigned types. There are a variety of ways one could define arithmetic and overflow for signed and unsigned types. Different methods have their advantages and disadvantages, and different programming languages pick different methods. In C, unsigned arithmetic is always modulo, and so overflows wrap around. That fits well with most hardware, and has a lot of practical benefits. But it also means that "u < u + 1" might be false, which is counter-intuitive for normal mathematics. You can take an unsigned number, keep adding to it, and suddenly end up with nothing. Signed arithmetic, on the other hand, never overflows in C. It is undefined behaviour - as far as the language is concerned, it can't happen. That means "x < x + 1" is /always/ true as far as C is concerned, for signed type x. This sort of thing makes mathematical sense, and gives compilers freedom to re-arrange and optimise code in a way that makes sense to programmers. You may think "I don't write conditionals like that" - but it can be surprising how often simple mathematical manipulation of expressions are valid when overflow cannot happen, but invalid in two's complement wraparound signed arithmetic. (An example is "(x * 2) / 2" -> "x".) Certain other behaviour, such as the conversion of an unsigned integer to a signed integer when the value won't fit, are left as implementation defined behaviour - basically, one should expect the most "natural" behaviour on the hardware, and this should be documented by the compiler. In many cases, this conversion will be modulo wraparound - but compilers /may/ do something else, if that operation would be expensive. Would it be nice to have different behaviour of C integers? Perhaps - it is certainly a valid viewpoint. Personally, I am happy with the way they work in most cases, but there are a few corner cases that I don't like. I would prefer automatic promotions of unsigned char and unsigned short to be to unsigned int, rather than signed int. I would like certain implementation-defined behaviour, such as the conversion to a signed integer mentioned above, to be "conditionally defined behaviour" - if the hardware uses two's complement signed integers, then such conversions should be defined as modulo wraparound, otherwise they can be implementation dependent. But whatever you think about the rules, however you think they could be different, however you imagine they /were/ different in some old version of C or some old compilers - the rules are there, they are clear and consistent, and there should not be a problem learning them and using them. > >> This is specified in N1570 6.5.7p4. >> >> (I don't recall that I've ever felt the need to left-shift a >> negative integer.) > > Have you even left-shifted an unsigned char expecting specifically > for the upper bits to disappear, instead of pulling the unsigned char > into and unsigned long to do the shift and then masking the upper > bits back out with a cast back to unsigned char? Unsigned chars promote to int (unless they are already the same size as int, in which case they work like unsigned int). An int can always represent all the values of the unsigned char as positive values, and left shifting of up to 7 bits is /always/ going to work correctly. Converting back to an unsigned char will always mask off any extra bits. So if you have code like: unsigned char uc = ...; int n = ...; uc = uc << n; Then the code will work as expected unless "n" shifts out /all/ the bits in the unsigned char (in which case it might work, and might not). > > And hoping the compiler (which often misses such optimizations) will > optimize out your excessive code on CPUs that will allocate a double > short register to do the long shift? Most compilers will handle code like the above quite well. <snip> > If I had the time, I'd go read it. I'm sure they thought they had a > good reason. > > I'll still push for splitting the standard if anyone is willing to > discuss it. You want to split and change the standard - but you haven't read it or the reasoning behind it? I'd study the rationale and the latest standard first, before trying to split it. (I don't think a rationale for C11 has been published.) > Embedded has drastically different needs than desktop or server, and > I even think desktop and server might be well served by fine-tuning > the standard to the target. I work with embedded programming all the time - I almost never use C on desktops or servers (usually I use Python for such work). And the more I learn about the subtleties of C - often from this group - the more I realise that there is very, very little I would want to change in this sort of area. There are a few points in the standard that would prefer to be modified. There are a number of gcc extensions or implementation-defined behaviours that I think are of significant benefit to my coding - and would therefore be useful in all compilers. There are a few (not many) points in the standard that I think could be simplified by assuming the target is a "normal" modern processor. There are a few changes or additions I would like in the standard library. And there are more than a few places where the standard could benefit from clearer language or better examples. But the fundamentals - including the way signed and unsigned work, and the undefined behaviours, I am happy with. > > -- Joel Rees > > "Is the standard made for man? Or is man made for the standard?" > > "Grasshopper. Go bother some other guru for a while." >
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-04-28 09:57 -0400 |
| Message-ID | <odvhhs$bik$1@dont-email.me> |
| In reply to | #108646 |
On 04/28/2017 04:19 AM, David Brown wrote: ... > Unsigned chars promote to int (unless they are already the same size as > int, in which case they work like unsigned int). Size isn't the relevant characteristic, though it is highly correlated with it. If UCHAR_MAX > INT_MAX, unsigned char promotes to unsigned int rather than int. > An int can always > represent all the values of the unsigned char as positive values, Change "always" to "usually", or at least "almost always". A fully conforming implementation can have UCHAR_MAX > INT_MAX. This is nit-picking, since such systems are rare, possibly non-existent - but you invite nit-picking when you insist on using absolutes such as "always". > ... and > left shifting of up to 7 bits is /always/ going to work correctly. Unless CHAR_BIT > 8, which happens on many real-world systems. > Converting back to an unsigned char will always mask off any extra bits. That, at least, is true.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-28 17:06 +0200 |
| Message-ID | <odvliu$q8k$1@dont-email.me> |
| In reply to | #108655 |
On 28/04/17 15:57, James Kuyper wrote: > On 04/28/2017 04:19 AM, David Brown wrote: > ... >> Unsigned chars promote to int (unless they are already the same size as >> int, in which case they work like unsigned int). > > Size isn't the relevant characteristic, though it is highly correlated > with it. If UCHAR_MAX > INT_MAX, unsigned char promotes to unsigned int > rather than int. > >> An int can always >> represent all the values of the unsigned char as positive values, > > Change "always" to "usually", or at least "almost always". A fully > conforming implementation can have UCHAR_MAX > INT_MAX. This is > nit-picking, since such systems are rare, possibly non-existent - but > you invite nit-picking when you insist on using absolutes such as "always". > Nit-picking is good - at least in this kind of discussion. So I am very happy to be corrected. I did mean to write "always" - but I intended that part to refer only to cases where unsigned chars promote to signed int rather than unsigned int (because if they are promoted to unsigned int, then the shift is done as unsigned and is fully defined with modulo wraparound semantics). I know of (and have used) systems where "char" and "int" are the same bit-size - a couple of 16-bit DSP devices and (briefly) a 32-bit DSP where int, short and char were all 16-bit or 32-bit respectively. Unsigned chars promote to unsigned int on such systems. >> ... and >> left shifting of up to 7 bits is /always/ going to work correctly. > > Unless CHAR_BIT > 8, which happens on many real-world systems. Let me see if I've got my reasoning correct here. (And as noted above, I am happy to be corrected if I've got something wrong. I'm splitting up the points into short paragraphs to make it easier to point out any mistakes.) CHAR_BIT must be at least 8 - this is the number of bits in an unsigned char (all of which must be value bits, not padding bits). An unsigned int must have at least as many value bits as CHAR_BIT, and at least 16 value bits, but can have padding bits as well. It must have a "pure binary" representation. A signed char must have exactly one sign bit, no padding bits, and CHAR_BIT - 1 value bits. Positive values must have the same representation as the same value of unsigned char. A signed int must have at least as many value bits as a signed char, and at least 15 value bits. It can have padding bits. Positive values must have the same representation (excluding padding bits) as for unsigned ints. It is possible for a signed int to have fewer value bits than an unsigned int, but nor more value bits. If UCHAR_MAX > INT_MAX, then there are unsigned char values that cannot be represented as signed ints. Therefore, unsigned char promotes to unsigned int for shifting. Since unsigned ints have defined overflow, it is safe to left-shift them by any non-negative amount less than the width of unsigned int. Since that width must be at least 16, it is safe to shift by up to 15 (and therefore up to 7). If UCHAR_MAX <= INT_MAX, unsigned char values promote to signed int (as positive values). It is safe to left-shift this as long as there is no overflow of the int. To be unsafe on a shift of 7 bits, that means the int must have fewer than 7 value bits above those of unsigned char, or a width (value bits plus sign bit) of less than 8 bits above that of an unsigned char. It must also have more than 0 extra bits (otherwise the unsigned char would have been promoted to unsigned int). And because a signed int has at least 16 bits of width, this means that we need a CHAR_BIT greater than 8, and a signed int whose representation is at least twice CHAR_BIT in raw bit size (since it is always a multiple of a char), but whose non-padding bit size is less than 8 bits more than that of a char. So we are talking about something like a 9-bit char, with an int being 16 bits of data with 2 padding bits. Yes, I can agree that this is possible by the C standards - but I don't think it will happen "on many real-world systems". > >> Converting back to an unsigned char will always mask off any extra bits. > > That, at least, is true. >
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-28 08:38 -0700 |
| Message-ID | <8cf3bfe6-1164-485f-8c00-a99f7e0cf96f@googlegroups.com> |
| In reply to | #108646 |
On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote:
> The context here is C programming unless explicitly stated otherwise,
> and in that context left-shifting a negative value is undefined.
Most people write code for actual machines, and so the context should be the
language processed for use on actual machines.
If the Standard had included the following two notes:
1. The fact that the Standard would allow an implementation targeting
a particular platform to behave in a certain way does not mean that
such behavior by that implementation would not be downright stupid
or obtuse.
2. The fact that a program targeting a particular platform might
malfunction when processed by an implementation which is downright
stupid or obtuse does not imply that it is defective.
that would undermine claims that the Standard requires programmers to jump
through hoops for portability even when the target platform is known. Such
statements would have been viewed as insulting and condescending (which is
likely why no such statements appear in the Standard) but I don't think
anyone could reasonably argue that the authors of the Standard intended the
opposite.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-28 18:51 +0200 |
| Message-ID | <odvro6$h92$1@dont-email.me> |
| In reply to | #108666 |
On 28/04/17 17:38, supercat@casperkitty.com wrote: > On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote: >> The context here is C programming unless explicitly stated otherwise, >> and in that context left-shifting a negative value is undefined. > > Most people write code for actual machines, and so the context should be the > language processed for use on actual machines. > Not in this newsgroup, no. The context is C programming - and what the C standards say overrules what happens to be the implementation details in some systems, precisely because implementations can vary so much. The standards are the /only/ fixed references we have - so they are the context unless explicitly stated otherwise. > If the Standard had included the following two notes: > > 1. The fact that the Standard would allow an implementation targeting > a particular platform to behave in a certain way does not mean that > such behavior by that implementation would not be downright stupid > or obtuse. > > 2. The fact that a program targeting a particular platform might > malfunction when processed by an implementation which is downright > stupid or obtuse does not imply that it is defective. > And if pigs could fly, you get your dog to do your coding. It is just as silly a hypothetical situation. > that would undermine claims that the Standard requires programmers to jump > through hoops for portability even when the target platform is known. Programmers /don't/ have to jump through hoops for portability when the target platform is known. You can write C code that it is tied to a specific target (processor, compiler, etc.) rather than portable code. This is one of the key uses of C from its first inception, and is a key use of it today. /Some/ code has to be maximally portable, some code has to be portable within certain limitations, and some code does not have to be portable at all. > Such > statements would have been viewed as insulting and condescending (which is > likely why no such statements appear in the Standard) but I don't think > anyone could reasonably argue that the authors of the Standard intended the > opposite. > You regularly claim to know the minds of the standards authors, and seem to think you know what they meant but did not write. Just because you cannot see any written evidence why might not have meant something, does not mean that they actually meant it but for some reason didn't write it.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-29 12:43 -0700 |
| Message-ID | <e58d2e1a-5bee-458b-a503-30244dbbf7fc@googlegroups.com> |
| In reply to | #108646 |
On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote:
> The context here is C programming unless explicitly stated otherwise,
> and in that context left-shifting a negative value is undefined.
Did C89 become off-topic? In C89, left-shifting a negative value was
defined in a way that made sense for two's-complement systems, but was
probably less than ideal on ones'-complement platforms (an implementation
which targeted ones' complement hardware could efficiently handle code
written for two's-complement machines if it made bitwise operators on
negative numbers behave as they would for two's-complement equivalents,
but the way C89 was written required that -1<<1 yield -3 rather than -2
on ones'-complement sytems).
It would seem likely that the authors of C99 wanted to allow implementations
to process left-shifts of negative numbers in whatever fashion would make
the most sense given the target platforms and purposes. Making the behavior
Undefined certainly has that effect. Is there any reason to believe that
it was intended to invite implementations where exactly one behavior would
make sense, to arbitrarily select other nonsensical behaviors instead?
BTW, I find it ironic that C99 went out of its way to acommodate sign-
magnitude and ones'-complement implementations, but then impose other
requirements that make it impractical to implement on such machines (are
there *any* conforming C99-or-later compilers for actual ones'-complement
hardware? Do they use 64-bit or larger word size, or do they somehow do
multi-word math in base 2)?
For that matter, does anyone know if the Univac 36-bit ones'-complement
system which has a 71-bit signed long long but no unsigned long long,
actually uses a pure binary notation for its signed long long type? I
would expect it would be much more efficient to use a type with a base of
2^36-1. If integers wrap mod that base, then given:
int v1h,v2h, resh;
nativeUnsigned v1l,v2l, resl; // Wrap mod 2^36-1 rather than mod 2^36
the sum could be computed, even without any "carry-flag" feature, via:
resultlower = v1l+v2l;
resultUpper = (v1l ^ v2l ^ resultLower) & 1 + v1h + v2h;
C99's requirement that all numbers use a pure binary representation would
forbid such an approach, however. I'm not sure exactly what hoops the
implementation had to jump through to achieve mod-2^36 unsigned arithmetic,
but I would expect it to make math on base-2^36 types much more expensive.
I don't know the Univac's instruction set, but would expect the above would
translate very straightforwardly into machine code with no branching; I
would expect code for unsigned long long to be a lot more complicated.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-04-30 14:02 -0700 |
| Message-ID | <kfn7f211ue0.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #108750 |
supercat@casperkitty.com writes:
> On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote:
>> The context here is C programming unless explicitly stated otherwise,
>> and in that context left-shifting a negative value is undefined.
>
> Did C89 become off-topic? In C89, left-shifting a negative value was
> defined in a way [...]
As he is wont to do, supercat is talking out of school here.
Before the C99 standard, a left shift of a negative value
is not defined behavior but implementation-defined behavior.
Quoting the official response in DR 81:
Subclause 6.3 states that the binary operator < , among
others, has implementation-defined aspects for signed types.
Therefore, the answer to ``What does it mean to left shift a
signed value?'' is that it is implementation-defined.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-30 14:25 -0700 |
| Message-ID | <ln37cpk2q7.fsf@kst-u.example.com> |
| In reply to | #108807 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
> supercat@casperkitty.com writes:
>> On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote:
>>> The context here is C programming unless explicitly stated otherwise,
>>> and in that context left-shifting a negative value is undefined.
>>
>> Did C89 become off-topic? In C89, left-shifting a negative value was
>> defined in a way [...]
>
> As he is wont to do, supercat is talking out of school here.
> Before the C99 standard, a left shift of a negative value
> is not defined behavior but implementation-defined behavior.
> Quoting the official response in DR 81:
>
> Subclause 6.3 states that the binary operator < , among
> others, has implementation-defined aspects for signed types.
> Therefore, the answer to ``What does it mean to left shift a
> signed value?'' is that it is implementation-defined.
It would be helpful if you'd Cite the DR you're referring to:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_081.html
(Note that the DR incorrectly refers to "<" rather than "<<",
presumably a typo.)
I'm not sure that supercat's interpretation is entirely unreasonable
given what the C90 standard actually says.
--
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 | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-04-30 15:01 -0700 |
| Message-ID | <kfnpoftzhaf.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #108810 |
Keith Thompson <kst-u@mib.org> writes: > Tim Rentsch <txr@alumni.caltech.edu> writes: >> supercat@casperkitty.com writes: >>> On Friday, April 28, 2017 at 3:19:17 AM UTC-5, David Brown wrote: >>>> The context here is C programming unless explicitly stated otherwise, >>>> and in that context left-shifting a negative value is undefined. >>> >>> Did C89 become off-topic? In C89, left-shifting a negative value was >>> defined in a way [...] >> >> As he is wont to do, supercat is talking out of school here. >> Before the C99 standard, a left shift of a negative value >> is not defined behavior but implementation-defined behavior. >> Quoting the official response in DR 81: >> >> Subclause 6.3 states that the binary operator < , among >> others, has implementation-defined aspects for signed types. >> Therefore, the answer to ``What does it mean to left shift a >> signed value?'' is that it is implementation-defined. > > It would be helpful if you'd Cite the DR you're referring to: > http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_081.html Yes, if I had had the URL handy then I might have thought to include it. But I didn't, so I didn't. > (Note that the DR incorrectly refers to "<" rather than "<<", > presumably a typo.) Right. By now I've read these things so many times I often miss the typos. > I'm not sure that supercat's interpretation is entirely > unreasonable given what the C90 standard actually says. It's perfectly reasonable if it had been qualified with an "I think that ..." or "It looks like ..." or something similar. I called it talking out of school because he offers the interpretation as an absolute certainty, without bothering to double check what should be an obvious red flag. He's been told about this before and he just doesn't bother. His screwy interpretations are wrong more often than not (or at least that is my strong impression), and I keep hoping he will exercise more due diligence in the future. Sorry to say he seems to have a very thick hide, and like he said in another posting he's a glutton for punishment. So I don't recommend that anyone hold their breath on that one.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-04-28 09:48 -0400 |
| Message-ID | <odvh1j$9op$1@dont-email.me> |
| In reply to | #108641 |
On 04/27/2017 11:20 PM, joel.rees@gmail.com wrote: > On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote: >> joel rees@somewhere writes: ... >>> (I know calling it brain-damaged is too extreme, but ...) >> >> I suggest you might benefit from describing these things in less >> inflammatory terms. > > Not sure how. If you avoid using such inflammatory terms, you'll find yourself avoiding thinking them too, which will greatly improve the quality and accuracy of your thinking. >> The behavor of left-shifting a negative value is undefined. > > Without context, I suppose it is. No, it's undefined behavior BECAUSE of the context, which includes the C standard. > But mapping it to a logical shift left on the CPU, whatever the CPU > gives for that, seems reasonable to me. Undefined behavior permits that choice, it just doesn't mandate it. > Far more reasonable than assuming that casting a minus one to an > unsigned type should always result in a bit mask of the type's width. I'm curious why you find that unreasonable. Understand - it isn't a special case rule for -1, it's a natural consequence of applying C's general rule for converting signed values to unsigned types. That rule was specifically designed so that on 2's complement machines (overwhelmingly the most common type), conversion of an m-bit signed integer value to an n-bit unsigned type is a no-op if m==n, and involves merely extracting the n lowest bits when n<m. This strikes you as an odd choice? >> This is specified in N1570 6.5.7p4. >> >> (I don't recall that I've ever felt the need to left-shift a negative >> integer.) > > Have you even left-shifted an unsigned char expecting specifically > for the upper bits to disappear, No. > ... instead of pulling the unsigned char into > and unsigned long to do the shift and then masking the upper bits back > out with a cast back to unsigned char? I'd just mask the value directly. > And hoping the compiler (which often misses such optimizations) will > optimize out your excessive code on CPUs that will allocate a double > short register to do the long shift? Keep in mind that if you write the code explicitly in the way you assume is most efficient, the compiler is free to disagree with you and generate machine instructions with equivalent behavior that corresponds more closely to the code you didn't want to write. If you don't trust the compiler to generate sufficiently efficient code, you shouldn't be using C, you should be using assembler, which gives you more control.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-28 08:07 -0700 |
| Message-ID | <6038480d-b90d-4b41-94f8-6a5374c54f31@googlegroups.com> |
| In reply to | #108641 |
On Thursday, April 27, 2017 at 10:20:18 PM UTC-5, joel...@gmail.com wrote:
> On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote:
> > The 1989 ANSI C committee had to choose between two schemes, both
> > implemented by existing compilers at the time: "unsigned preserving" and
> > "value preserving". They chose the latter. (I think I would have
> > preferred unsigned preserving semantics myself, but I haven't taken the
> > time to think about possible disadvantages.) This is discussed in the
> > C99 Rationale, section 6.3.1.1, available at
> > http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf .
>
> If I had the time, I'd go read it. I'm sure they thought they had a good reason.
Do read it, and you'll see that despite what other people here claim, the
authors of the Standard were expecting that even though the Standard made
allowances for platforms that performed integer arithmetic in weird ways,
they expected implementations to evolve toward handling things like
unsigned mul(unsigned short x, unsigned short y) { return x*y; }
in sensible fashion even in cases where the result is between INT_MAX+1U and
UINT_MAX.
Incidentally, the reason that (unsigned)-1 has all bits set is that the
Standard requires that UINT_MAX be one smaller than a power of two, adding
1 to UINT_MAX gives zero, and adding x to -x gives zero. Put those together
and (unsigned)-1 is required to give a number which, when added to 1, yields
zero.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-28 18:56 +0200 |
| Message-ID | <odvs1r$iar$1@dont-email.me> |
| In reply to | #108661 |
On 28/04/17 17:07, supercat@casperkitty.com wrote:
> On Thursday, April 27, 2017 at 10:20:18 PM UTC-5, joel...@gmail.com wrote:
>> On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote:
>>> The 1989 ANSI C committee had to choose between two schemes, both
>>> implemented by existing compilers at the time: "unsigned preserving" and
>>> "value preserving". They chose the latter. (I think I would have
>>> preferred unsigned preserving semantics myself, but I haven't taken the
>>> time to think about possible disadvantages.) This is discussed in the
>>> C99 Rationale, section 6.3.1.1, available at
>>> http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf .
>>
>> If I had the time, I'd go read it. I'm sure they thought they had a good reason.
>
> Do read it, and you'll see that despite what other people here claim, the
> authors of the Standard were expecting that even though the Standard made
> allowances for platforms that performed integer arithmetic in weird ways,
> they expected implementations to evolve toward handling things like
>
> unsigned mul(unsigned short x, unsigned short y) { return x*y; }
>
> in sensible fashion even in cases where the result is between INT_MAX+1U and
> UINT_MAX.
>
Read the rationale, and you'll see there is no evidence for this claim
whatsoever.
Just because the standards committee did not write explicitly "lets add
a fun trap to catch people trying to multiply unsigned shorts" in either
the standards or the rationales, does /not/ mean that they really meant
to write "here are all the rules for integer promotions, implicit
conversions, expression evaluation, etc., all written out clearly and
consistently for a balance between compiler freedom to optimise, support
for varied target architectures, efficient code generation, and ease of
learning and ease of use for the programmer. And we'll add one special
exception just for our dear friend Supercat - if you want to multiply
two unsigned shorts, the rules are different."
> Incidentally, the reason that (unsigned)-1 has all bits set is that the
> Standard requires that UINT_MAX be one smaller than a power of two, adding
> 1 to UINT_MAX gives zero, and adding x to -x gives zero. Put those together
> and (unsigned)-1 is required to give a number which, when added to 1, yields
> zero.
>
Or, as has been explained in far simpler terms, unsigned arithmetic is
done as modulo arithmetic in C.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-28 11:30 -0700 |
| Message-ID | <6368c3c6-2cf6-4296-bc53-5789b293fafc@googlegroups.com> |
| In reply to | #108675 |
On Friday, April 28, 2017 at 11:56:34 AM UTC-5, David Brown wrote: > Read the rationale, and you'll see there is no evidence for this claim > whatsoever. Read it and draw your own conclusions. > Just because the standards committee did not write explicitly "lets add > a fun trap to catch people trying to multiply unsigned shorts" in either > the standards or the rationales, does /not/ mean that they really meant > to write "here are all the rules for integer promotions, implicit > conversions, expression evaluation, etc., all written out clearly and > consistently for a balance between compiler freedom to optimise, support > for varied target architectures, efficient code generation, and ease of > learning and ease of use for the programmer. And we'll add one special > exception just for our dear friend Supercat - if you want to multiply > two unsigned shorts, the rules are different." The rationale notes that on the majority of implementations, singed and unsigned operations will behave identically except in certain specific situations. If the authors of the Standard didn't mean to imply that they would exhibit such behavior *even in cases where the Standard would not require it* there would have been no need to limit such discussion merely to those implementations that use silent-wraparound two's-complement semantics.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-28 08:35 -0700 |
| Message-ID | <lnshkslf3y.fsf@kst-u.example.com> |
| In reply to | #108641 |
joel.rees@gmail.com writes:
> On Friday, April 28, 2017 at 7:21:14 AM UTC+9, Keith Thompson wrote:
>> joel rees@somewhere writes:
>> [...]
>> > We have this coddling of brain-damaged CPUs when a left-shift on a
>> > negative operand is specified on sign-magnitude architectures or
>> > something, but we have this assurance that casting a -1 to an unsigned
>> > fills the thing with ones.
>> >
>> > (I know calling it brain-damaged is too extreme, but ...)
>>
>> I suggest you might benefit from describing these things in less
>> inflammatory terms.
>
> Not sure how.
Well, avoiding terms like "brain-damaged" and "purism" would be a good
start.
>> The behavor of left-shifting a negative value is undefined.
>
> Without context, I suppose it is.
What context? The behavior is undefined. The C standard says so.
Of course an implementation can choose to define the behavior
for itself.
> But mapping it to a logical shift left on the CPU, whatever the CPU
> gives for that, seems reasonable to me.
Sure, that's a reasonable way to implement the "<<" operator, assuming
that the CPU's shift operator implements the required semantics.
But the C standard specifies how programs behave, not what CPU
instructions are used to implement that behavior. And compilers can
and do take advantage of undefined behavior to perform optimizations.
If you want a language where a shift operator means "apply the CPU's
logical shift instruction", you want something other than C.
> Far more reasonable than assuming that casting a minus one to an
> unsigned type should always result in a bit mask of the type's width.
You don't have to assume it. It follows from the semantics specified by
the C standard, and it's guaranteed.
>> This is specified in N1570 6.5.7p4.
>>
>> (I don't recall that I've ever felt the need to left-shift a negative
>> integer.)
>
> Have you even left-shifted an unsigned char expecting specifically for
> the upper bits to disappear, instead of pulling the unsigned char into
> and unsigned long to do the shift and then masking the upper bits back
> out with a cast back to unsigned char?
Not that I recall. If I needed to shift an unsigned char, I'd probably
cast it to unsigned int to avoid problems. (I'm not particularly happy
that that's needed.)
[...]
>> http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf .
>
> If I had the time, I'd go read it. I'm sure they thought they had a
> good reason.
>
> I'll still push for splitting the standard if anyone is willing to
> discuss it.
I'd say that reading and understanding the standard (and the Rationale)
is a prerequisite to making major changes.
[...]
Incidentally, it would be very helpful if you'd format your posts to
about 72 columns. Google Groups makes it unreasonably difficult to do
so.
--
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 | 2017-04-28 00:54 +0200 |
| Message-ID | <odtskd$sn1$1@dont-email.me> |
| In reply to | #108629 |
(Please get a real newsreader and server, rather than google groups.)
On 27/04/17 23:35, joel.rees@gmail.com wrote:
> On Thursday, April 27, 2017 at 7:59:40 PM UTC+9, Ben Bacarisse wrote:
>> joel rees@somewhere writes:
>>
<snip>
> You know, it's funny.
>
> We have this coddling of brain-damaged CPUs when a left-shift on a
> negative operand is specified on sign-magnitude architectures or
> something, but we have this assurance that casting a -1 to an
> unsigned fills the thing with ones.
Left shift of negative integers is like most signed integer overflows -
the result is undefined (but an implementation can define it if it wants
to).
>
>
> (I know calling it brain-damaged is too extreme, but ...)
>
> And I have a hard time remembering that assurance is in the standard.
> Maybe it's because I don't really use sign-magnitude that much.
Basically, unsigned arithmetic always works as modulo arithmetic.
Signed arithmetic is not allowed to overflow. It's actually quite
simple and consistent.
>
> The standards committee gets to tilt at windmills, and I get to chase
> their rainbows.
>
> I really wish the standards committee had instead specified a means
> of compile-time testing the architecture for the specific corner- and
> edge-cases and providing a means to either pop up a warning to remind
> the reader of compiler output that the code wasn't intended to be
> compiled on that particular architecture, or use conditional compiled
> sections to deal with the corner-case on those CPUs.
>
There isn't really anything to test at compile time here. Don't let
your signed arithmetic overflow - it does not matter if the underlying
hardware is sign-magnitude, two's complement, or whatever.
> A few more hours of their work to help a thousand guys like me to cut
> a few wasted days off of tilting with our own windmills every now and
> again.
>
>>> byteWidth = i;
>>> i = 0;
>>> while ( ulroller != 0 )
>>> { ulroller <<= 1;
>>> ++i;
>>> }
>>> ulBytes = i / byteWidth;
>>
>> What's wrong with
>>
>> ulBytes = sizeof (unsigned long);
>>
>> ?
>
> Well, since you ask, you're right. Either way requires run-time behavior.
sizeof(unsigned long) is fixed at compile time, and even half-decent
compilers will optimise accordingly.
[toc] | [prev] | [next] | [standalone]
| From | joel.rees@gmail.com |
|---|---|
| Date | 2017-04-27 21:05 -0700 |
| Message-ID | <2bf49ed4-ded6-4a40-9563-bfde4fa96c6d@googlegroups.com> |
| In reply to | #108631 |
On Friday, April 28, 2017 at 8:01:45 AM UTC+9, David Brown wrote:
> (Please get a real newsreader and server, rather than google groups.)
You got a favorite?
I'm using googlemail because google insists on fighting with sylpheed, but googlecode sure drags the browser through the mud and heats the engines up mercilessly.
> On 27/04/17 23:35, joel rees@somewhere wrote:
> > On Thursday, April 27, 2017 at 7:59:40 PM UTC+9, Ben Bacarisse wrote:
> >> joel rees@somewhere writes:
> >>
> <snip>
> > You know, it's funny.
> >
> > We have this coddling of brain-damaged CPUs when a left-shift on a
> > negative operand is specified on sign-magnitude architectures or
> > something, but we have this assurance that casting a -1 to an
> > unsigned fills the thing with ones.
>
> Left shift of negative integers is like most signed integer overflows -
> the result is undefined (but an implementation can define it if it wants
> to).
When you assume that's an overflow and not a truncation, that seems
correct.
I was, for various reasons, looking for the truncation, and now I
see that the standard says I should say, what was it? (Dragging
it in from my source code instead of looking back to the previous
post.) Instead of:
chMask = ( chMask << 1 ) | 1;
I should say
chMask = (unsigned char)
( ( ( (unsigned long) chMask ) << 1 ) | 1 );
> > (I know calling it brain-damaged is too extreme, but ...)
> >
> > And I have a hard time remembering that assurance is in the standard.
> > Maybe it's because I don't really use sign-magnitude that much.
>
> Basically, unsigned arithmetic always works as modulo arithmetic.
> Signed arithmetic is not allowed to overflow. It's actually quite
> simple and consistent.
If you know that unsigned char gets promoted to signed int, as Keith Thompson pointed out to me. Somehow, I missed that all those years ago.
> > The standards committee gets to tilt at windmills, and I get to chase
> > their rainbows.
> >
> > I really wish the standards committee had instead specified a means
> > of compile-time testing the architecture for the specific corner- and
> > edge-cases and providing a means to either pop up a warning to remind
> > the reader of compiler output that the code wasn't intended to be
> > compiled on that particular architecture, or use conditional compiled
> > sections to deal with the corner-case on those CPUs.
> >
>
> There isn't really anything to test at compile time here. Don't let
> your signed arithmetic overflow - it does not matter if the underlying
> hardware is sign-magnitude, two's complement, or whatever.
Well, you seem to be talking about the shift when I'm talking about
the idiom by that point.
On a sign-magnitude architecture, I think I'd prefer, instead of the
idiom, that
(unsigned char) -1
hmm. What would I prefer?
signed char thing = -1;
unsigned char uthing = (unsigned long) thing;
should give me, depending on the sign-magnitude implementation,
something like 0x81 in uthing.
Is thing promoted before the cast?
> > A few more hours of their work to help a thousand guys like me to cut
> > a few wasted days off of tilting with our own windmills every now and
> > again.
> >
> >>> byteWidth = i;
> >>> i = 0;
> >>> while ( ulroller != 0 )
> >>> { ulroller <<= 1;
> >>> ++i;
> >>> }
> >>> ulBytes = i / byteWidth;
> >>
> >> What's wrong with
> >>
> >> ulBytes = sizeof (unsigned long);
> >>
> >> ?
> >
> > Well, since you ask, you're right. Either way requires run-time behavior.
>
> sizeof(unsigned long) is fixed at compile time, and even half-decent
> compilers will optimise accordingly.
But the last time I tried to use sizeof in a context that required
the expression to evaluate to a constant at compile time, the
compiler said I was being a naughty boy and would get no pudding that
day.
I ended up using a bunch of ifdefs to pick the right constant.
The code I'm working on this time should not have that constraint,
although I'm not sure if I want to take the time to go fix it.
Calling my initialization function fixed my problem for now.
It's not exactly critical code, but it's in a blog post where
it might lead some future generations astray. ;-)
--
Joel Rees
Delusions of being a novelist:
http://joel-rees-economics.blogspot.com/2017/01/soc500-00-00-toc.html
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-28 10:58 +0200 |
| Message-ID | <odv01r$fd6$1@dont-email.me> |
| In reply to | #108643 |
On 28/04/17 06:05, joel.rees@gmail.com wrote:
> On Friday, April 28, 2017 at 8:01:45 AM UTC+9, David Brown wrote:
>> (Please get a real newsreader and server, rather than google
>> groups.)
>
> You got a favorite?
A very popular combination is Thunderbird as the newsreader, and
news.eternal-september.org as the free newsserver. It works for Linux,
Windows and Mac. Google groups is fine for researching old posts, but a
poor interface for daily newsgroup usage. And it screws up line splits,
which is a pain for everyone else!
(I don't want to start a discussion about different newsreader clients
here - I just want to let you know that you will be happier, and we will
be happier, if you switch from google groups. Now back to C.)
>
> I'm using googlemail because google insists on fighting with
> sylpheed, but googlecode sure drags the browser through the mud and
> heats the engines up mercilessly.
>
>> On 27/04/17 23:35, joel rees@somewhere wrote:
>>> On Thursday, April 27, 2017 at 7:59:40 PM UTC+9, Ben Bacarisse
>>> wrote:
>>>> joel rees@somewhere writes:
>>>>
>> <snip>
>>> You know, it's funny.
>>>
>>> We have this coddling of brain-damaged CPUs when a left-shift on
>>> a negative operand is specified on sign-magnitude architectures
>>> or something, but we have this assurance that casting a -1 to an
>>> unsigned fills the thing with ones.
>>
>> Left shift of negative integers is like most signed integer
>> overflows - the result is undefined (but an implementation can
>> define it if it wants to).
>
> When you assume that's an overflow and not a truncation, that seems
> correct.
It /is/ an overflow, not a truncation. Mathematically, left shift is
multiplying by 2. Assuming 16-bit integers because the numbers are
smaller and easier, in what way could 16386 * 2 evaluating to -32768 be
described as a truncation rather than an overflow? That is what happens
when you left-shift a signed integer that is too large.
Or how about -3072 * 2 evaluating to 4096? Left shift of negative
signed integers, implemented as a simple hardware shift, gives
meaningless results.
For /unsigned/ arithmetic with modulo behaviour, you are truncating the
highest bits - that is what modulo does.
>
> I was, for various reasons, looking for the truncation, and now I see
> that the standard says I should say, what was it? (Dragging it in
> from my source code instead of looking back to the previous post.)
> Instead of:
>
> chMask = ( chMask << 1 ) | 1;
>
> I should say
>
> chMask = (unsigned char) ( ( ( (unsigned long) chMask ) << 1 ) | 1 );
No, it does not say that. It is safe to write
chMask = ( chMask << 1 ) | 1
(By the way, there is only one thing I think is less useful than using
"Systems Hungarian" notation with variable names prefixed by an
abbreviation of their type - and that is to use it incorrectly and
inconsistently. But that is style, and not part of the behaviour of the
code.)
>
>>> (I know calling it brain-damaged is too extreme, but ...)
>>>
>>> And I have a hard time remembering that assurance is in the
>>> standard. Maybe it's because I don't really use sign-magnitude
>>> that much.
>>
>> Basically, unsigned arithmetic always works as modulo arithmetic.
>> Signed arithmetic is not allowed to overflow. It's actually quite
>> simple and consistent.
>
> If you know that unsigned char gets promoted to signed int, as Keith
> Thompson pointed out to me. Somehow, I missed that all those years
> ago.
I cannot remember when I learned about "integer promotions" - but they
are in ยง6.3.1.1 of the C11 standard. This newsgroup is a great place to
ask about that sort of thing.
And now you /do/ know about it, allowing you to simplify your code.
(And if ever Keith posts something about the standards that contradicts
what I write, believe Keith.)
>
>>> The standards committee gets to tilt at windmills, and I get to
>>> chase their rainbows.
>>>
>>> I really wish the standards committee had instead specified a
>>> means of compile-time testing the architecture for the specific
>>> corner- and edge-cases and providing a means to either pop up a
>>> warning to remind the reader of compiler output that the code
>>> wasn't intended to be compiled on that particular architecture,
>>> or use conditional compiled sections to deal with the corner-case
>>> on those CPUs.
>>>
>>
>> There isn't really anything to test at compile time here. Don't
>> let your signed arithmetic overflow - it does not matter if the
>> underlying hardware is sign-magnitude, two's complement, or
>> whatever.
>
> Well, you seem to be talking about the shift when I'm talking about
> the idiom by that point.
>
> On a sign-magnitude architecture, I think I'd prefer, instead of the
> idiom, that
>
> (unsigned char) -1
>
> hmm. What would I prefer?
>
> signed char thing = -1; unsigned char uthing = (unsigned long)
> thing;
>
> should give me, depending on the sign-magnitude implementation,
> something like 0x81 in uthing.
>
Having never used a sign-magnitude architecture (and I hope I never have
to!), I can't say what I would /prefer/ here. But I know how C works,
and it says such conversions to unsigned types are done as modulo.
If you want to get the underlying bit representation of the signed
integer here, then the tool you are looking for is "union" - /not/
conversions.
> Is thing promoted before the cast?
No. (But it would make no difference if it were.)
>
>>> A few more hours of their work to help a thousand guys like me to
>>> cut a few wasted days off of tilting with our own windmills every
>>> now and again.
>>>
>>>>> byteWidth = i; i = 0; while ( ulroller != 0 ) { ulroller <<=
>>>>> 1; ++i; } ulBytes = i / byteWidth;
>>>>
>>>> What's wrong with
>>>>
>>>> ulBytes = sizeof (unsigned long);
>>>>
>>>> ?
>>>
>>> Well, since you ask, you're right. Either way requires run-time
>>> behavior.
>>
>> sizeof(unsigned long) is fixed at compile time, and even
>> half-decent compilers will optimise accordingly.
>
> But the last time I tried to use sizeof in a context that required
> the expression to evaluate to a constant at compile time, the
> compiler said I was being a naughty boy and would get no pudding that
> day.
Ah, there is a big difference between "something that the compiler knows
is constant at compilation time" and "something that the C language says
is a "constant expression". The former can be used for optimisation
purposes, but only the later can be used in things like "#if" directives.
>
> I ended up using a bunch of ifdefs to pick the right constant.
Everything you need is conveniently available in <limits.h>, saving you
the effort.
>
> The code I'm working on this time should not have that constraint,
> although I'm not sure if I want to take the time to go fix it.
>
> Calling my initialization function fixed my problem for now. It's not
> exactly critical code, but it's in a blog post where it might lead
> some future generations astray. ;-)
>
> -- Joel Rees
>
> Delusions of being a novelist:
> http://joel-rees-economics.blogspot.com/2017/01/soc500-00-00-toc.html
>
[toc] | [prev] | [next] | [standalone]
Page 4 of 7 — ← Prev page 1 2 3 [4] 5 6 7 Next page →
Back to top | Article view | comp.lang.c
csiph-web