Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Portable 16 bit binary integer write Date: Sat, 17 Sep 2016 15:04:28 -0700 Organization: None to speak of Lines: 78 Message-ID: References: <50a1e8f4-4fb3-4491-97d0-54768bf28685@googlegroups.com> <4fde1133-61ff-4045-9cbe-cccff1408ad3@googlegroups.com> <0b757bbb-0494-44cb-bd5a-26f117aaa404@googlegroups.com> <2cf666d7-0755-4c70-adad-07dbafc2b2e7@googlegroups.com> <09cb4413-16a6-4b63-89d0-9dafe56562f6@googlegroups.com> <68e53f3a-5fcc-44fc-90c4-bcf8dc3db680@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="945944de09706c9b4e29b53c9d2efdc2"; logging-data="15415"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/DpWBSvP9bOR3s79RSRJvq" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:PwMyWWYCVKBPc2+jcl1plXaC2cw= sha1:OsZ5qGaqolkK9xHWmEx1YK+NJgQ= Xref: csiph.com comp.lang.c:93689 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 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"