472,989 Members | 3,144 Online

# Negative values in unsigned int

I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99. What is the semantic when you decrement an
unsigned int below 0 (or subtract two unsigned ints with negative
result)? AFAIR, this results in implementation-defined behavior but
not undefined behavior. Is that correct?

So what does the standard say to this code?

void f(void)
{
unsigned int n = 0;
n--;
}

Also, do I have implementation-defined or undefined behavior, if I
decrement below zero but don't use the value, as in the following
code?

void f(unsigned int n)
{
while (n-- 0) { /* In the last loop iteration, n is
; decremented from 0, but not used
} afterwards */
}

A short notice with section number in the standard would be nice
(as I think section numbering in my draft version is not that
different).

urs
Sep 8 '08 #1
13 10554
On Mon, 08 Sep 2008 14:38:16 +0200, Urs Thuermann wrote:
So what does the standard say to this code?
unsigned int n = 0;
n--;
Always results in UINT_MAX.
Also, do I have implementation-defined or undefined behavior, if I
decrement below zero but don't use the value, as in the following code?

void f(unsigned int n)
{
while (n-- 0) { /* In the last loop iteration, n is
; decremented from 0, but not used
} afterwards */
}
This evaluates the greater-than with the original value of n, then
decrements n. n is automatic so its value is lost when the function
returns.
Sep 8 '08 #2
Urs Thuermann wrote:
I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99. What is the semantic when you decrement an
unsigned int below 0 (or subtract two unsigned ints with negative
result)? AFAIR, this results in implementation-defined behavior but
not undefined behavior. Is that correct?
No. It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."
So what does the standard say to this code?

void f(void)
{
unsigned int n = 0;
n--;
At this point, the value of n must be UINT_MAX.
}

Also, do I have implementation-defined or undefined behavior, if I
decrement below zero but don't use the value, as in the following
code?

void f(unsigned int n)
{
while (n-- 0) { /* In the last loop iteration, n is
; decremented from 0, but not used
} afterwards */
}
Since the behavior is standard-defined, you don't have to worry about
it; whether or not the resulting value gets used doesn't matter. If
the behavior were undefined (as, for example, INT_MAX+1), then the
fact that you didn't use the result still wouldn't protect your code,
at least in principle. As a practical matter, since the value is not
used, an optimizing compiler might remove the calculation that
produced the value, reducing the opportunities for undesireable
consequences - but you should never write code which relies upon this.

Sep 8 '08 #3
Urs Thuermann wrote:
>
I wasn't able to find an answer to the following questions in a
draft version of IOS 9899-99. What is the semantic when you
decrement an unsigned int below 0 (or subtract two unsigned ints
with negative result)? AFAIR, this results in implementation-
defined behavior but not undefined behavior. Is that correct?
No. It is carefully defined. Unsigned quantities do arithmetic
modulo the (maximum unsigned value + 1).

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Sep 8 '08 #4
Urs Thuermann <ur*@isnogud.escape.dewrites:
I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99.
<snip>
A short notice with section number in the standard would be nice
(as I think section numbering in my draft version is not that
different).
Mostly answered except for this bit. The main rule at work is 6.3.1.3
paragraph 2.

--
Ben.
Sep 8 '08 #5
ja*********@verizon.net wrote:
Urs Thuermann wrote:
>I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99. What is the semantic when you decrement an
unsigned int below 0 (or subtract two unsigned ints with negative
result)? AFAIR, this results in implementation-defined behavior but
not undefined behavior. Is that correct?

No.
Yes.
It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."
Note the part beginning "the largest value ...". That
value is implementation-defined, hence the value of the
result is implementation-defined.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Sep 14 '08 #6
On Sun, 14 Sep 2008 17:20:16 -0400, Eric Sosman
<es*****@ieee-dot-org.invalidwrote:
>ja*********@verizon.net wrote:
>Urs Thuermann wrote:
>>I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99. What is the semantic when you decrement an
unsigned int below 0 (or subtract two unsigned ints with negative
result)? AFAIR, this results in implementation-defined behavior but
not undefined behavior. Is that correct?

No.

Yes.
>It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

Note the part beginning "the largest value ...". That
value is implementation-defined, hence the value of the
result is implementation-defined.
The value is implementation defined but the behavior is not. The
behavior is defined as quoted. Your approach would also render the
behavior of
int x = '0' < '1';
is also implementation defined since the values of '0' and '1' are
implementation dependent.

--
Remove del for email
Sep 14 '08 #7
Eric Sosman wrote:
ja*********@verizon.net wrote:
>Urs Thuermann wrote:
>>I wasn't able to find an answer to the following questions in a draft
version of IOS 9899-99. What is the semantic when you decrement an
unsigned int below 0 (or subtract two unsigned ints with negative
result)? AFAIR, this results in implementation-defined behavior but
not undefined behavior. Is that correct?

No.

Yes.
>It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

Note the part beginning "the largest value ...". That
value is implementation-defined, hence the value of the
result is implementation-defined.
No, that's implementation-dependent result, but not
implementation-defined behavior. The implementation gets to decide for
each unsigned type what the value of TYPE_MAX is. Having made that
decision, they get no additional freedom in the value that results from
overflow or underflow for unsigned; there's a standard-defined
relationship between the two values.
Sep 15 '08 #8
Barry Schwarz wrote:
>
.... snip ...
>
The value is implementation defined but the behavior is not. The
behavior is defined as quoted. Your approach would also render
the behavior of
int x = '0' < '1';
is also implementation defined since the values of '0' and '1'
are implementation dependent.
However since '1' is known to have the value ('0' + 1) that x is
thoroughly defined. If you picked 'a' and 'b' I could agree.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Sep 15 '08 #9
ja*********@verizon.net writes:
No. It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."
OK, Thanx. I've read the 1989 edition of the standard 10 or so years
ago and I had in mind that this would result in implementation-defined
behavior, but I probably confused that with the signed integer case
(which also is not implementation-defined but undefined if I read the
the standard correctly).
void f(unsigned int n)
{
while (n-- 0) { /* In the last loop iteration, n is
; decremented from 0, but not used
} afterwards */
}

Since the behavior is standard-defined, you don't have to worry about
it; whether or not the resulting value gets used doesn't matter. If
the behavior were undefined (as, for example, INT_MAX+1), then the
fact that you didn't use the result still wouldn't protect your code,
at least in principle.
Yes, that is what I assumed also.
As a practical matter, since the value is not used, an optimizing
compiler might remove the calculation that produced the value,
reducing the opportunities for undesireable consequences - but you
should never write code which relies upon this.
Yes, of course. I had a function which does somthing similar to

void f(int n)
{
while (--n >= 0)
do_something();
}

and I wanted to change the parameter n to unsigned int like this

void f(unsigned int n)
{
while (n-- 0)
do_something();
}

and then I wondered what happens when n is 0 in the last loop
iteration. But your answer did clarify this completely, thanks
again.

urs
Sep 17 '08 #10
On 17 Sep 2008 09:58:28 +0200, Urs Thuermann <ur*@isnogud.escape.de>
wrote:
>ja*********@verizon.net writes:
>No. It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

OK, Thanx. I've read the 1989 edition of the standard 10 or so years
ago and I had in mind that this would result in implementation-defined
behavior, but I probably confused that with the signed integer case
(which also is not implementation-defined but undefined if I read the
the standard correctly).
It was in C89 but no longer in C99.

--
Remove del for email
Sep 18 '08 #11
Barry Schwarz <sc******@dqel.comwrites:
On 17 Sep 2008 09:58:28 +0200, Urs Thuermann <ur*@isnogud.escape.de>
wrote:
>>ja*********@verizon.net writes:
>>No. It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

OK, Thanx. I've read the 1989 edition of the standard 10 or so years
ago and I had in mind that this would result in implementation-defined
behavior, but I probably confused that with the signed integer case
(which also is not implementation-defined but undefined if I read the
the standard correctly).

It was in C89 but no longer in C99.
It's undefined in both C89/C90 and C99.

C99 6.5p5:

If an _exceptional condition_ occurs during the evaluation of an
expression (that is, if the result is not mathematically defined
or not in the range of representable values for its type), the
behavior is undefined.

C90 has the same wording.

Perhaps you're thinking of C99's change in the semantics of
conversions. In C99, a conversion to a signed type of a value that
can't be represented in that type either yields an
implementation-defined result or raises an implementation-defined
signal (C99 6.3.1.3p3); in C90, the result is implementation-defined
(it couldn't raise a signal).

(Out-of-range conversions to a floating-point type invoke undefined
behavior in both C90 and C99.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 18 '08 #12
On Wed, 17 Sep 2008 21:30:22 -0700, Keith Thompson <ks***@mib.org>
wrote:
>Barry Schwarz <sc******@dqel.comwrites:
>On 17 Sep 2008 09:58:28 +0200, Urs Thuermann <ur*@isnogud.escape.de>
wrote:
>>>ja*********@verizon.net writes:

No. It is standard-defined behavior. Section 6.2.5p9 says:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

OK, Thanx. I've read the 1989 edition of the standard 10 or so years
ago and I had in mind that this would result in implementation-defined
behavior, but I probably confused that with the signed integer case
(which also is not implementation-defined but undefined if I read the
the standard correctly).

It was in C89 but no longer in C99.

It's undefined in both C89/C90 and C99.

C99 6.5p5:

If an _exceptional condition_ occurs during the evaluation of an
expression (that is, if the result is not mathematically defined
or not in the range of representable values for its type), the
behavior is undefined.

C90 has the same wording.

Perhaps you're thinking of C99's change in the semantics of
conversions. In C99, a conversion to a signed type of a value that
can't be represented in that type either yields an
implementation-defined result or raises an implementation-defined
signal (C99 6.3.1.3p3); in C90, the result is implementation-defined
(it couldn't raise a signal).

(Out-of-range conversions to a floating-point type invoke undefined
behavior in both C90 and C99.)
But the thread (or at least what I could see of it) appeared to be
talking about converting an unsigned value to a signed integer and for
C99 the relevant paragraph seems to be 6.3.1.3-3 which says
"Otherwise, the new type is signed and the value cannot be represented
in it; either the result is implementation-defined or an
implementation-defined signal is raised."

--
Remove del for email
Sep 19 '08 #13
Barry Schwarz <sc******@dqel.comwrites:
On Wed, 17 Sep 2008 21:30:22 -0700, Keith Thompson <ks***@mib.org>
wrote:
>>Barry Schwarz <sc******@dqel.comwrites:
>>On 17 Sep 2008 09:58:28 +0200, Urs Thuermann <ur*@isnogud.escape.de>
wrote:
[...]
>>>>OK, Thanx. I've read the 1989 edition of the standard 10 or so years
ago and I had in mind that this would result in implementation-defined
behavior, but I probably confused that with the signed integer case
(which also is not implementation-defined but undefined if I read the
the standard correctly).

It was in C89 but no longer in C99.

It's undefined in both C89/C90 and C99.

C99 6.5p5:

If an _exceptional condition_ occurs during the evaluation of an
expression (that is, if the result is not mathematically defined
or not in the range of representable values for its type), the
behavior is undefined.

C90 has the same wording.

Perhaps you're thinking of C99's change in the semantics of
conversions. In C99, a conversion to a signed type of a value that
can't be represented in that type either yields an
implementation-defined result or raises an implementation-defined
signal (C99 6.3.1.3p3); in C90, the result is implementation-defined
(it couldn't raise a signal).

(Out-of-range conversions to a floating-point type invoke undefined
behavior in both C90 and C99.)

But the thread (or at least what I could see of it) appeared to be
talking about converting an unsigned value to a signed integer and for
C99 the relevant paragraph seems to be 6.3.1.3-3 which says
"Otherwise, the new type is signed and the value cannot be represented
in it; either the result is implementation-defined or an
implementation-defined signal is raised."
Then I'm unclear on what you meant by "It was in C89 but no longer in
C99." I thought you meant that something (out-of-range conversion to
a signed type, probably) was undefined in C89, but is no longer
undefined in C99, which is not the case.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 19 '08 #14

This thread has been closed and replies have been disabled. Please start a new discussion.