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-14 18:09 signed/unsigned right shift Christian Groessler
@ 2004-03-14 18:23 ` Ian Lance Taylor
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Lance Taylor @ 2004-03-14 18:23 UTC (permalink / raw)
  To: Christian Groessler; +Cc: GCC List

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?

Usual arithmetic conversions performed on operands of multiplication:
6.5.5.

Usual arithmetic conversions: 6.3.1.8.  Note in particular "the
integer promotions are performed on both operands."

Integer promotions: 6.3.1.1.

Right shift of signed negative value implementation defined: 6.5.7.

Ian

^ 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:14 ` Andreas Schwab
@ 2004-03-15 22:18   ` Andreas Schwab
  0 siblings, 0 replies; 10+ messages in thread
From: Andreas Schwab @ 2004-03-15 22:18 UTC (permalink / raw)
  To: Christian Groessler; +Cc: Ian Lance Taylor, GCC List

Andreas Schwab <schwab@suse.de> writes:

> Christian Groessler <cpg@aladdin.de> writes:
>
>> But sentence 3 says "The integer promotions preserve value including
>> sign."
>>
>> So shouldn't the conversion be "unsigned short" to "unsigned int"?
>
> No, it just says that the _value_ is preserved.  It doesn't say anything
> about the type.  That's one of the key difference between K&R C and ISO
> C: type preservation vs. value preservation.

s/type preservation/unsigned preservation/

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ 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
  1 sibling, 0 replies; 10+ messages in thread
From: Ian Lance Taylor @ 2004-03-15 22:17 UTC (permalink / raw)
  To: Christian Groessler; +Cc: GCC List

Christian Groessler <cpg@aladdin.de> writes:

> 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"?

Sentence 3 means that both the value and the sign of the value (i.e.,
positive or negative) are preserved.

Your suggestion would be expressed as "The integer promotions preserve
value including signedness."

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

Ian

^ 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:18   ` Andreas Schwab
  2004-03-15 22:17 ` Ian Lance Taylor
  1 sibling, 1 reply; 10+ messages in thread
From: Andreas Schwab @ 2004-03-15 22:14 UTC (permalink / raw)
  To: Christian Groessler; +Cc: Ian Lance Taylor, GCC List

Christian Groessler <cpg@aladdin.de> writes:

> But sentence 3 says "The integer promotions preserve value including
> sign."
>
> So shouldn't the conversion be "unsigned short" to "unsigned int"?

No, it just says that the _value_ is preserved.  It doesn't say anything
about the type.  That's one of the key difference between K&R C and ISO
C: type preservation vs. value preservation.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ 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

* Re: signed/unsigned right shift
  2004-03-12 22:24 ` Andreas Schwab
@ 2004-03-12 22:37   ` Dale Johannesen
  0 siblings, 0 replies; 10+ messages in thread
From: Dale Johannesen @ 2004-03-12 22:37 UTC (permalink / raw)
  To: Christian Groessler; +Cc: Dale Johannesen, Andreas Schwab, GCC List

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.

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

* Re: signed/unsigned right shift
  2004-03-12 21:25 Christian Groessler
@ 2004-03-12 22:24 ` Andreas Schwab
  2004-03-12 22:37   ` Dale Johannesen
  0 siblings, 1 reply; 10+ messages in thread
From: Andreas Schwab @ 2004-03-12 22:24 UTC (permalink / raw)
  To: Christian Groessler; +Cc: gcc

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.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ 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).