public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: signed/unsigned right shift
@ 2004-03-14 18:09 Christian Groessler
  2004-03-14 18:23 ` Ian Lance Taylor
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Groessler @ 2004-03-14 18:09 UTC (permalink / raw)
  To: GCC List

On 03/12/2004 02:34:46 PM PST Dale Johannesen wrote:
>
>On Mar 12, 2004, at 2:24 PM, Andreas Schwab wrote:
>> Christian Groessler <cpg@aladdin.de> writes:
>>> I have the following program which takes 2 unsigned short values,
>>> multiplies them and shifts the result right.
>>>
>>> This right shift gives a value with 1s bits at the high end.
>>
>> This is correct.  The promotion rules let unsigned short promote to
>> int,
>> since the latter can represent all values of the former.
>
>Correct, the multiplication is done as signed int.  And it is
>implementation
>defined whether right shift of a negative signed int does sign fill or
>not.
>So both compilers are right; it is only your code that's wrong.
>
>C89 references: 3.3.7, 3.2.1.5, 3.2.1.1.

Hmm, unfortunately I don't have the c89 standard document. Can
somebody point me to the equvalent sections in c99?

regards,
chris

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: signed/unsigned right shift
@ 2004-03-15 22:24 Christian Groessler
  0 siblings, 0 replies; 10+ messages in thread
From: Christian Groessler @ 2004-03-15 22:24 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: GCC List

On 03/15/2004 05:16:55 PM EST Ian Lance Taylor wrote:
>
>Christian Groessler <cpg@aladdin.de> writes:
>
>Your suggestion would be expressed as "The integer promotions preserve
>value including signedness."

Yes, that's how I read it erroneously.


>K&R C was signedness preserving.  ISO C is value preserving.  A quick
>Google search turned up this page on the topic:
>    http://ou800doc.caldera.com/SDK_cprog/_Background.html

That's putting it to the point.

Thanks to all who responded.

regards,
chris

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: signed/unsigned right shift
@ 2004-03-15 22:02 Christian Groessler
  2004-03-15 22:14 ` Andreas Schwab
  2004-03-15 22:17 ` Ian Lance Taylor
  0 siblings, 2 replies; 10+ messages in thread
From: Christian Groessler @ 2004-03-15 22:02 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: GCC List

On 03/14/2004 01:23:18 PM EST Ian Lance Taylor wrote:
>
>Christian Groessler <cpg@aladdin.de> writes:
>
>> >Correct, the multiplication is done as signed int.  And it is
>> >implementation
>> >defined whether right shift of a negative signed int does sign fill or
>> >not.
>> >So both compilers are right; it is only your code that's wrong.
>> >
>> >C89 references: 3.3.7, 3.2.1.5, 3.2.1.1.
>>
>> Hmm, unfortunately I don't have the c89 standard document. Can
>> somebody point me to the equvalent sections in c99?
>

>Integer promotions: 6.3.1.1.

Sentence 2 says "If an int can represent all values of the original
type, the value is converted to an int; otherwise, it is converted to
an unsigned int."

Seems to suggest that the conversion "unsigned short" to "signed int"
is ok.

But sentence 3 says "The integer promotions preserve value including
sign."

So shouldn't the conversion be "unsigned short" to "unsigned int"?

regards,
chris

^ permalink raw reply	[flat|nested] 10+ messages in thread
* signed/unsigned right shift
@ 2004-03-12 21:25 Christian Groessler
  2004-03-12 22:24 ` Andreas Schwab
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Groessler @ 2004-03-12 21:25 UTC (permalink / raw)
  To: gcc

Hello,

I have the following program which takes 2 unsigned short values,
multiplies them and shifts the result right.

This right shift gives a value with 1s bits at the high end. I think
it should give 0s there.


---- test program ---
unsigned int bug(long long uu, long long vv)
{
  union {
    unsigned long long ll;
    unsigned short s[4];
  } u, v;

  u.ll = (unsigned long long)uu;
  v.ll = (unsigned long long)vv;

  printf("u.s[0] = %04x, v.s[1] = %04x\n", u.s[0], v.s[1]);

  return (u.s[0] * v.s[1]) >> 16;
}

int main(void)
{
  long long u;
  long long v;

  u = 0x8f669000ll;
  v = 0xe4f06000ll;

  printf("%08x\n", bug(u, v));
  return 0;
}
---- test program ---

The output is 


u.s[0] = 9000, v.s[1] = e4f0
ffff80c7


If I write the last line of the bug function like

return (unsigned)(u.s[0] * v.s[1]) >> 16;

it works like I expected and gives


u.s[0] = 9000, v.s[1] = e4f0
000080c7


I post this here since with 3 different compilers tried only gcc gives
this result.

Sorry if this behaviour is a C feature I shouldn't have asked here,
and if it is, please point me to the according section in the
standard.

regards,
chris

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-03-15 22:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-14 18:09 signed/unsigned right shift Christian Groessler
2004-03-14 18:23 ` Ian Lance Taylor
  -- strict thread matches above, loose matches on Subject: below --
2004-03-15 22:24 Christian Groessler
2004-03-15 22:02 Christian Groessler
2004-03-15 22:14 ` Andreas Schwab
2004-03-15 22:18   ` Andreas Schwab
2004-03-15 22:17 ` Ian Lance Taylor
2004-03-12 21:25 Christian Groessler
2004-03-12 22:24 ` Andreas Schwab
2004-03-12 22:37   ` Dale Johannesen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).