C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Signed mod unsigned
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language
View previous topic :: View next topic  
Author Message
Johannes Bauer
Guest





PostPosted: Wed Jun 06, 2012 11:55 am    Post subject: Signed mod unsigned Reply with quote



Hi group,

today I ran into something I honestly did not expect. Consider this snippet:

#include <stdio.h>

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

Best regards,
Joe

--
Quote:
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen

Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$1 (AT) speranza (DOT) aioe.org>
Back to top
James Kuyper
Guest





PostPosted: Wed Jun 06, 2012 12:41 pm    Post subject: Re: Signed mod unsigned Reply with quote



On 06/06/2012 09:55 AM, Johannes Bauer wrote:
Quote:
Hi group,

today I ran into something I honestly did not expect. Consider this snippet:

#include <stdio.h

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

In most binary expressions (modulus expressions are no exception -
6.5.5p3), the operands are subject to what is called the usual
arithmetic conversions (6.3.1.Cool before the operation is performed.
Those conversions include the integer promotions, which leave both
operands unchanged in this case. The relevant rule is that when one
promoted type is unsigned, and the other is signed, if the unsigned type
has an integer conversion rank greater than or equal to that of the
signed type, then the operand of the signed type is converted to the
unsigned type. "unsigned int" is required to have the same integer
conversion rank as "int" (6.3.1.1p1);

So the behavior you describe is not only allowed, but required, by the C
standard. There's some minor details about your description that should
be modified: this is not an example of what the C standard calls a
promotion, and it has nothing to do with 2's complement. The C standard
also allows 1's complement and sign-magnitude representations
(6.2.6.2p2), and the conversion from a signed value to an unsigned type
follows the same rules regardless of the representation used for the
signed type. A value 1 greater than the maximum value representable in
the unsigned type is either repeatedly added to, or repeatedly subtract
from, the value until the result is representable in the unsigned type
(6.3.1.3p2).

The machine instructions needed to obtain this result can be quite
different, depending upon which representation is used for the signed
type. However, the result of the conversion should be exactly the same
for all three representations, it depends only upon the initial value
represented and maximum representable value of the unsigned type.
Back to top
gwowen
Guest





PostPosted: Wed Jun 06, 2012 2:53 pm    Post subject: Re: Signed mod unsigned Reply with quote



On Jun 6, 2:55 pm, Johannes Bauer <dfnsonfsdu...@gmx.de> wrote:
Quote:

Is this really in accordance with the C standard or is gcc doing
something weird here?


James has given a complete technical answer, so I won't add to that.
What I will say is that there's no universally accepted definition of
what remainder/modulus means, so whatever intuition tells you[0],
someone is going to consider it to be wrong.

When it comes to remainders involving negatives, intuition is
worthless.

[0] My intuition, for example, tells me that -1 % 30 equals 29. My
intuition is worthless too.
Back to top
James Kuyper
Guest





PostPosted: Wed Jun 06, 2012 8:29 pm    Post subject: Re: Signed mod unsigned Reply with quote

On 06/06/2012 06:15 PM, Edward Rutherford wrote:
Quote:
Johannes Bauer wrote:

Hi group,

today I ran into something I honestly did not expect. Consider this
snippet:

#include <stdio.h

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

This looks like a compiler bug. I would report it to a Gcc mailing list.

I explained in my response why I believe that this behavior is not
merely allowed, but mandated, by the C standard. Do you disagree? If so,
on what grounds?
Back to top
Edward Rutherford
Guest





PostPosted: Wed Jun 06, 2012 10:15 pm    Post subject: Re: Signed mod unsigned Reply with quote

Johannes Bauer wrote:

Quote:
Hi group,

today I ran into something I honestly did not expect. Consider this
snippet:

#include <stdio.h

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

This looks like a compiler bug. I would report it to a Gcc mailing list.
Back to top
Johannes Bauer
Guest





PostPosted: Thu Jun 07, 2012 8:12 am    Post subject: Re: Signed mod unsigned Reply with quote

On 06.06.2012 16:41, James Kuyper wrote:

[...]

Quote:
So the behavior you describe is not only allowed, but required, by the C
standard.

James, thank you very much for the verbose and detailed explanation. In
15 years of C programming, I did not run into that caveat :-)

Best regards,
Johannes

--
Quote:
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen

Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$1 (AT) speranza (DOT) aioe.org>
Back to top
Johannes Bauer
Guest





PostPosted: Thu Jun 07, 2012 8:15 am    Post subject: Re: Signed mod unsigned Reply with quote

On 06.06.2012 16:53, gwowen wrote:

Quote:
When it comes to remainders involving negatives, intuition is
worthless.

[0] My intuition, for example, tells me that -1 % 30 equals 29. My
intuition is worthless too.

Well, it's always nice when intuition at least overlaps with the reality
of compilers or interpreters :-)

BTW, -1 % 30 == 29 in Python. I did know that C did not give up the
sign, but I'd have expected for example -100 % 30 == -10 (it is 20 in
Python). Anyways, it does so for signed/signed types, so I'm going to
use these.

Best regards,
Joe

--
Quote:
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen

Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$1 (AT) speranza (DOT) aioe.org>
Back to top
James Kuyper
Guest





PostPosted: Thu Jun 07, 2012 8:44 am    Post subject: Re: Signed mod unsigned Reply with quote

On 06/07/2012 06:12 AM, Johannes Bauer wrote:
Quote:
On 06.06.2012 16:41, James Kuyper wrote:

[...]

So the behavior you describe is not only allowed, but required, by the C
standard.

James, thank you very much for the verbose and detailed explanation. In
15 years of C programming, I did not run into that caveat Smile

This issue comes up in almost every binary operation involving negative
values and unsigned integers of a type with equal or greater integer
conversion rank; if you've not noticed it before in 15 years of C
programming, then you've probably been deliberately avoiding mixing
negative values with unsigned types - which is generally a good idea.
--
James Kuyper
Back to top
BartC
Guest





PostPosted: Thu Jun 07, 2012 9:29 am    Post subject: Re: Signed mod unsigned Reply with quote

Johannes Bauer" <dfnsonfsduifb (AT) gmx (DOT) de> wrote in message
news:jqpv0d$beq$1 (AT) news (DOT) albasani.net...
Quote:
On 06.06.2012 16:53, gwowen wrote:

[0] My intuition, for example, tells me that -1 % 30 equals 29. My
intuition is worthless too.

Well, it's always nice when intuition at least overlaps with the reality
of compilers or interpreters :-)

BTW, -1 % 30 == 29 in Python. I did know that C did not give up the
sign, but I'd have expected for example -100 % 30 == -10 (it is 20 in
Python). Anyways, it does so for signed/signed types, so I'm going to
use these.

So -1%30 is -1 in C and 29 in Python. While -1%30u in C is 15.

-1, 15 and 29; any other possible results for the same expression?

--
Bartc
Back to top
Johannes Bauer
Guest





PostPosted: Thu Jun 07, 2012 9:31 am    Post subject: Re: Signed mod unsigned Reply with quote

On 07.06.2012 12:44, James Kuyper wrote:

Quote:
if you've not noticed it before in 15 years of C
programming, then you've probably been deliberately avoiding mixing
negative values with unsigned types - which is generally a good idea.

I try to do arithmetic, indexing and counting (i.e. loop variables) with
signed types and use unsigned almost always only for bit operations (or
where the well-defined overflow is needed). Has worked well so far :-)

Best regards,
Joe

--
Quote:
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen

Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$1 (AT) speranza (DOT) aioe.org>
Back to top
Johannes Bauer
Guest





PostPosted: Thu Jun 07, 2012 9:43 am    Post subject: Re: Signed mod unsigned Reply with quote

On 07.06.2012 13:29, BartC wrote:

Quote:
BTW, -1 % 30 == 29 in Python. I did know that C did not give up the
sign, but I'd have expected for example -100 % 30 == -10 (it is 20 in
Python). Anyways, it does so for signed/signed types, so I'm going to
use these.

So -1%30 is -1 in C and 29 in Python. While -1%30u in C is 15.

-1, 15 and 29; any other possible results for the same expression?

If I understand James' post correct, in the expression -1 % 30u the "-1"
is converted to UNSIGNED_MAX (which happens to be (2^32)-1 on my system).

Since int IIRC is only required to have >= 16 bits, one could image a
n-bit system in which the expression would evaluate to something
different. In particular, if bits % 4 == 0, it evaluates to 15. For

bits % 4 result
0 15
1 1
2 3
3 7

So I think the expression can be either -1, 15, 29, 1, 3 or 7 depending
on the language and platform :-)

Best regards,
Johannes

--
Quote:
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen

Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$1 (AT) speranza (DOT) aioe.org>
Back to top
Eric Sosman
Guest





PostPosted: Thu Jun 07, 2012 9:46 am    Post subject: Re: Signed mod unsigned Reply with quote

On 6/7/2012 7:29 AM, BartC wrote:
Quote:
Johannes Bauer" <dfnsonfsduifb (AT) gmx (DOT) de> wrote in message
news:jqpv0d$beq$1 (AT) news (DOT) albasani.net...
On 06.06.2012 16:53, gwowen wrote:

[0] My intuition, for example, tells me that -1 % 30 equals 29. My
intuition is worthless too.

Well, it's always nice when intuition at least overlaps with the reality
of compilers or interpreters :-)

BTW, -1 % 30 == 29 in Python. I did know that C did not give up the
sign, but I'd have expected for example -100 % 30 == -10 (it is 20 in
Python). Anyways, it does so for signed/signed types, so I'm going to
use these.

So -1%30 is -1 in C and 29 in Python. While -1%30u in C is 15.

-1%30u in C *can be* 15.

Quote:
-1, 15 and 29; any other possible results for the same expression?

In C, the possible results are 1, 3, 7, 15.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Back to top
Ben Bacarisse
Guest





PostPosted: Thu Jun 07, 2012 5:58 pm    Post subject: Re: Signed mod unsigned Reply with quote

Eric Sosman <esosman@ieee-dot-org.invalid> writes:

Quote:
On 6/7/2012 7:29 AM, BartC wrote:
Johannes Bauer" <dfnsonfsduifb (AT) gmx (DOT) de> wrote in message
news:jqpv0d$beq$1 (AT) news (DOT) albasani.net...
On 06.06.2012 16:53, gwowen wrote:

[0] My intuition, for example, tells me that -1 % 30 equals 29. My
intuition is worthless too.

Well, it's always nice when intuition at least overlaps with the reality
of compilers or interpreters :-)

BTW, -1 % 30 == 29 in Python. I did know that C did not give up the
sign, but I'd have expected for example -100 % 30 == -10 (it is 20 in
Python). Anyways, it does so for signed/signed types, so I'm going to
use these.

So -1%30 is -1 in C and 29 in Python. While -1%30u in C is 15.

-1%30u in C *can be* 15.

-1, 15 and 29; any other possible results for the same expression?

In C, the possible results are 1, 3, 7, 15.

I think -1 is also possible on those awkward systems where UINT_MAX ==
INT_MAX.

--
Ben.
Back to top
James Kuyper
Guest





PostPosted: Thu Jun 07, 2012 7:08 pm    Post subject: Re: Signed mod unsigned Reply with quote

On 06/07/2012 04:44 PM, Edward Rutherford wrote:
Quote:
James Kuyper wrote:

On 06/06/2012 06:15 PM, Edward Rutherford wrote:
Johannes Bauer wrote:

Hi group,

today I ran into something I honestly did not expect. Consider this
snippet:

#include <stdio.h

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

This looks like a compiler bug. I would report it to a Gcc mailing
list.

I explained in my response why I believe that this behavior is not
merely allowed, but mandated, by the C standard. Do you disagree? If so,
on what grounds?

This outcome just seems counterintuitive to me. Even if it is permitted
by the C standard, this option is kinda retarded and I'd say the compiler
has poor quality of implementation.

It's not merely permitted; it's not an option; it's required. The phrase
"Quality of implementation" is normally considered to apply only to
issues where the standard gives a conforming implementation freedom to
choose how something is done. The only freedom that the implementation
has that's relevant to this program is in number of value bits in an
unsigned int. You're not suggesting, I hope, that choosing 32 for that
number gives the implementation a low QoI? It's a pretty popular choice.
Back to top
Edward Rutherford
Guest





PostPosted: Thu Jun 07, 2012 8:44 pm    Post subject: Re: Signed mod unsigned Reply with quote

James Kuyper wrote:

Quote:
On 06/06/2012 06:15 PM, Edward Rutherford wrote:
Johannes Bauer wrote:

Hi group,

today I ran into something I honestly did not expect. Consider this
snippet:

#include <stdio.h

int main() {
int i1, i2;
unsigned int u2;

i1 = -1;

i2 = 30;
u2 = 30;

printf("%d\n", i1 % i2);
printf("%d\n", i1 % u2);
return 0;
}

I expected to find the output "-1 / -1". Instead the result I got was
"-1 / 15". Apparently when getting the remainder of a signed by a
unsigned int, the signed is silently promoted to unsigned in twos
complement and then the operation is performed, i.e.

0xffffffff % 30 == 15

I would have expected at least a warning since I find this highly
unintuitive -- my expectation would be that the unsigned becomes a
(truncated) signed and a warning. Instead gcc does not emit a warning
(-Wall -Wextra) and silently performs above operation.

Is this really in accordance with the C standard or is gcc doing
something weird here?

This looks like a compiler bug. I would report it to a Gcc mailing
list.

I explained in my response why I believe that this behavior is not
merely allowed, but mandated, by the C standard. Do you disagree? If so,
on what grounds?

This outcome just seems counterintuitive to me. Even if it is permitted
by the C standard, this option is kinda retarded and I'd say the compiler
has poor quality of implementation.

Best regards,
E.P.R.
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
 


Powered by phpBB © 2001, 2006 phpBB Group