By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,236 Members | 1,843 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,236 IT Pros & Developers. It's quick & easy.

unsigned short addition/subtraction overflow

P: n/a
Hi,
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;

TIA
Andy
Nov 14 '05 #1
Share this Question
Share on Google+
34 Replies


P: n/a
On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;


Yes.

-- James
Nov 14 '05 #2

P: n/a
James Hu wrote:

On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;


Yes.


No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.

--
pete
Nov 14 '05 #3

P: n/a

"pete" <pf*****@mindspring.com> schrieb im Newsbeitrag
news:3F***********@mindspring.com...
James Hu wrote:

On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;


Yes.


No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.


From N869: 6.2.5
9 The range of nonnegative values of a signed integer type is a subrange of
the
corresponding unsigned integer type, and the representation of the same
value in each
type is the same.28) 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.

However, I am not sure about
i = 1 - 3;
and
li = 1 - 3;
but I think it is defined as far as I understand the integer promotion
rules.

cheers
Robert
Nov 14 '05 #4

P: n/a
pete wrote:
James Hu wrote:
On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;


Yes.


No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.


Good catch. However, change "would" to "could".

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #5

P: n/a
Robert Stankowic wrote:

"pete" <pf*****@mindspring.com> schrieb im Newsbeitrag
news:3F***********@mindspring.com...
James Hu wrote:

On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
> Are 1 through 4 defined behaviors in C?
>
> unsigned short i;
> unsigned long li; /* 32-bit wide */
>
> 1. i = 65535 + 3;
> 2. i = 1 - 3;
> 3. li = (unsigned long)0xFFFFFFFF + 3;
> 4. li = 1 - 3;

Yes.
No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.


From N869: 6.2.5
9 The range of nonnegative values of a
signed integer type is a subrange of
the corresponding unsigned integer type,
and the representation of the same value in each
type is the same.28)
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.


What's your point ?
If INT_MAX equals 65535,
then there are no unsigned operands in (65535 + 3), just two ints.
However, I am not sure about
i = 1 - 3;
and
li = 1 - 3;
but I think it is defined as far as I
understand the integer promotion rules.


The standard defines what happens when any integer
is the right operand of the assignment operator,
and the left operand is an unsigned type.

--
pete
Nov 14 '05 #6

P: n/a
CBFalconer wrote:

pete wrote:
James Hu wrote:
On 2003-12-21, Andy <bi*****@hotmail.com> wrote:

> Are 1 through 4 defined behaviors in C?
>
> unsigned short i;
> unsigned long li; /* 32-bit wide */
>
> 1. i = 65535 + 3;
> 2. i = 1 - 3;
> 3. li = (unsigned long)0xFFFFFFFF + 3;
> 4. li = 1 - 3;

Yes.


No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.


Good catch. However, change "would" to "could".


I think I got that right.
"in that case" meaning the case when 65536 was equal to INT_MAX,
then (65535 + 3) most definitely would overflow,
and definitely be undefined behavior.
The particular form of the manifestation of the undefined behavior,
would be different matter, if that's what you mean.

--
pete
Nov 14 '05 #7

P: n/a
pete wrote:

Robert Stankowic wrote:

"pete" <pf*****@mindspring.com> schrieb im Newsbeitrag
news:3F***********@mindspring.com...
James Hu wrote:
>
> On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
> > Are 1 through 4 defined behaviors in C?
> >
> > unsigned short i;
> > unsigned long li; /* 32-bit wide */
> >
> > 1. i = 65535 + 3;
> > 2. i = 1 - 3;
> > 3. li = (unsigned long)0xFFFFFFFF + 3;
> > 4. li = 1 - 3;
>
> Yes.

No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.
From N869: 6.2.5
9 The range of nonnegative values of a
signed integer type is a subrange of
the corresponding unsigned integer type,
and the representation of the same value in each
type is the same.28)
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.


What's your point ?
If INT_MAX equals 65535,


I meant 65536.
then there are no unsigned operands in (65535 + 3), just two ints.
However, I am not sure about
i = 1 - 3;
and
li = 1 - 3;
but I think it is defined as far as I
understand the integer promotion rules.


The standard defines what happens when any integer
is the right operand of the assignment operator,
and the left operand is an unsigned type.


--
pete
Nov 14 '05 #8

P: n/a
bi*****@hotmail.com (Andy) wrote in message news:<ae**************************@posting.google. com>...
Hi,
Are 1 through 4 defined behaviors in C?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = 65535 + 3;
2. i = 1 - 3;
3. li = (unsigned long)0xFFFFFFFF + 3;
4. li = 1 - 3;

TIA
Andy


Actually what I really meant is for unsigned operations.
This is what I want to know. Are the following defined in
C and always guaranteed warped around values?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = (unsigned short)65535 + (unsigned short)3;
2. i = (unsigned short)1 - (unsigned short)3;
3. li = (unsigned long)0xFFFFFFFF + (unsigned long)3;
4. li = (unsigned long)1 - (unsigned long)3;

TIA
Andy
Nov 14 '05 #9

P: n/a

"pete" <pf*****@mindspring.com> schrieb im Newsbeitrag
news:3F***********@mindspring.com...
pete wrote:

Robert Stankowic wrote:

"pete" <pf*****@mindspring.com> schrieb im Newsbeitrag
[....]
What's your point ?
If INT_MAX equals 65535,


I meant 65536.
then there are no unsigned operands in (65535 + 3), just two ints.


I see your point.
Thanks
Robert
Nov 14 '05 #10

P: n/a
pete wrote:

No.
65536 is an allowable value for INT_MAX.


I don't think so. INT_MAX pretty much has to be an odd number, I think.
In fact, to satisfy the requirement that the non-negative integer values
have the same representation as the same values for the corresponding
unsigned type, and the requirement that unsigned types use a pure binary
representation, I think it's safe to say that INT_MAX must be (2^N)-1
for some integer N, which must be 15 or greater.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #11

P: n/a
Andy wrote:

Actually what I really meant is for unsigned operations.
This is what I want to know. Are the following defined in
C and always guaranteed warped around values?

unsigned short i;
unsigned long li; /* 32-bit wide */

1. i = (unsigned short)65535 + (unsigned short)3;
You could write these easer this way:

i = 65535u + 3u;
2. i = (unsigned short)1 - (unsigned short)3;
3. li = (unsigned long)0xFFFFFFFF + (unsigned long)3;
4. li = (unsigned long)1 - (unsigned long)3;


It's difficult to produce undefined behavior with unsigned values.
(Unless you divide by zero, maybe. I don't actually know what the
standard says about that, which surprises me.) Overflow doesn't occur
with unsigned types, but it's possible for unsigned types that are
narrower than int to be promoted to (signed) int, which may allow
overflow (and undefined behavior) to occur.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #12

P: n/a
On 2003-12-21, pete <pf*****@mindspring.com> wrote:
James Hu wrote:

On 2003-12-21, Andy <bi*****@hotmail.com> wrote:
> Are 1 through 4 defined behaviors in C?
>
> unsigned short i;
> unsigned long li; /* 32-bit wide */
>
> 1. i = 65535 + 3;
> 2. i = 1 - 3;
> 3. li = (unsigned long)0xFFFFFFFF + 3;
> 4. li = 1 - 3;


Yes.


No.
65536 is an allowable value for INT_MAX.
(65535 + 3) would be integer overflow
and undefined behavior in that case.


Good catch. I did consider overflow, but I assumed that (65535+3) was
identical to writing (65538) because of computation at translation
time versus computation at run time.

-- James
Nov 14 '05 #13

P: n/a
>Andy wrote:
Actually what I really meant is for unsigned operations.
This is what I want to know. Are the following defined in
C and always guaranteed warped around values?

unsigned short i;
unsigned long li; /* 32-bit wide */
All C guarantees here is "at least" 32 bits, but here it does
not really matter.
1. i = (unsigned short)65535 + (unsigned short)3;
In article <vC***************@newsread2.news.pas.earthlink.ne t>
Kevin Goodsell <us*********************@neverbox.com> writes:
You could write these easer this way:

i = 65535u + 3u;
Actually, this is potentially quite different.

If ANSI/ISO C used the *correct* rules (according to me :-) )
it would be precisely the same, but we are stuck with quite
bogus widening rules due to a mistaken decision in the 1980s:
"when a narrow unsigned integer type widens, the resulting
type is signed if all the unsigned values fit, otherwise
it is unsigned".

In this particular case, unsigned short widens to either
unsigned int or signed int. Which one we get depends on the
properties of the implementation. This is a really dumb idea,
made in an attempt to be "less surprising" than the "right"
way ("narrow unsigned widens to unsigned"), that actually
turns out to be *more* surprising. But again we are stuck
with the wrong decision -- so let me define it.

What you must do is look in <limits.h> (perhaps by writing a
small C program, since the header may not exist) and compare
the values of USHRT_MAX and INT_MAX. One of the following two
cases will necessarily hold:

a) USHRT_MAX > INT_MAX.

This occurs on, e.g., the 16-bit PDP-11 and old 16-bit
MS-DOS C compilers. Here USHRT_MAX is 65535 while INT_MAX
is 32767.

b) USHRT_MAX <= INT_MAX.

This occurs on, e.g., today's 16-bit-short 32-bit-int C
compilers. Here USHRT_MAX is 65535 while INT_MAX is
2147483647.

In case (a), an unsigned short expression -- no matter what its
actual value is -- that appears in an arithmetic expression is
widened to unsigned int. Thus (unsigned short)65535 is
identical to (unsigned int)65535 or 65535U.

In case (b), howver, an unsigned short -- no matter what its actual
value is -- is widened to a *signed* int. Thus (unsigned short)65535
is identical to (int)65535 or 65535.

If we have two "unsigned short"s, values 65535 and 3 respectively,
and go to add them, we continue to have "case a" and "case b".
In case (a), the sum is 65535U + 3U, which has type unsigned int
and value 2. In case (b), the sum is 65535 + 3, which has type
signed int and value 65538.

In either case, when storing the final values back into an unsigned
short, it is reduced mod (USHRT_MAX+1), so that i becomes 2. The
place where this becomes a problem is not when we stuff the result
back into an unsigned variable, but rather when we compare it in
what the original 1989 C rationale called a "questionably signed"
expression.

Suppose we have the following code fragment:

unsigned short us = 65535;
int i = -1;

if (us > i)
printf("65535 > -1\n");
else
printf("65535 <= -1\n");

According to ANSI C's ridiculous rules (which we must obey anyway),
we decide whether this comparison uses "unsigned int" or "signed
int" based on whether USHRT_MAX exceeds INT_MAX. Once again, we
have the two cases:

case (a), USHRT_MAX > INT_MAX (PDP-11): "us" widens to an
unsigned int, value 65535U; i widens to an unsigned int,
value 65535U. 65535U > 65535U is false and we print
"65535 <= -1". This is, supposedly, "surprising" -- but
it happens!

case (b), USHRT_MAX < INT_MAX (VAX etc): "us" widens to
a signed int, value 65535; i remains signed int, value
-1. 65535 > -1 is true and we print "65535 > -1". This
is supposedly "not surprising" (which is probably true),
but in fact it is only SOMETIMES true.

As far as I am concerned, it is *much* better to be "predictably
surprising" than "unpredictably surprising based on the relative
values of USHRT_MAX and INT_MAX". The reason is that, while C
programmers do get surprised, they get surprised *once*, the *first*
time they mix signed and unsigned this way. This gives them the
opportunity to learn that the results are surprising; from then
on, they have no excuse to be surprised. Moreover, the logic
is trivial to follow: "unsigned widens to unsigned" means "put
an unsigned into an expression and it takes over."

Instead, we have a language where the code "works as expected" --
until it is moved to a machine where case (a) holds instead of case
(b). Programmers learn that mixing signed and unsigned is harmless
and "never surprises", only to find someday that, no, the language
is considerably more perverse than that. The logic is difficult
as well: "unsigned takes over except when it doesn't, based on the
relative values of the corresponding MAXes."
2. i = (unsigned short)1 - (unsigned short)3;
3. li = (unsigned long)0xFFFFFFFF + (unsigned long)3;
4. li = (unsigned long)1 - (unsigned long)3;

It's difficult to produce undefined behavior with unsigned values.
As long as you stick with unsigned int or unsigned long, anyway,
so that the broken widening rules do not trick you into accidentally
using signed values.
(Unless you divide by zero, maybe. I don't actually know what the
standard says about that, which surprises me.)
Division by zero produces undefined behavior, even for 1U / 0U and
the like.
Overflow doesn't occur
with unsigned types, but it's possible for unsigned types that are
narrower than int to be promoted to (signed) int, which may allow
overflow (and undefined behavior) to occur.


Yes. I claim that this rule is a terrible one; but I note that we
are stuck with it. The best approach is to avoid it -- make sure
you explicitly widen your narrow unsigned types to wider unsigned
types if the result (overflow or result of "questionably signed"
comparison) can matter. This kind of code is undeniably ugly, but
then, working around broken portions of any language (not just C)
is usually ugly.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #14

P: n/a
Chris Torek wrote:
In article <vC***************@newsread2.news.pas.earthlink.ne t>
Kevin Goodsell <us*********************@neverbox.com> writes:
You could write these easer this way:

i = 65535u + 3u;

Actually, this is potentially quite different.


Yes, obviously. Not sure what I was thinking there. I think I suffer
from "short blindness" - I either miss the word 'short' or
sub-consciously translate it to 'int'. This wasn't the first time.

Thanks for pointing out the error.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #15

P: n/a
Kevin Goodsell wrote:

pete wrote:

No.
65536 is an allowable value for INT_MAX.


I don't think so.


65535
Thank you.

--
pete
Nov 14 '05 #16

P: n/a
pete <pf*****@mindspring.com> wrote in message news:<3F***********@mindspring.com>...
pete wrote:

....
If INT_MAX equals 65535,


I meant 65536.


Why? Neither is likely, but 65536 is considerably less so. Some would
argue (myself included) that 65536 is impossible on a conforming
implementation (be that C90 or C99).

--
Peter
Nov 14 '05 #17

P: n/a
Peter Nilsson wrote:

pete <pf*****@mindspring.com> wrote in message news:<3F***********@mindspring.com>...
pete wrote:

...
If INT_MAX equals 65535,


I meant 65536.


Why? Neither is likely, but 65536 is considerably less so. Some would
argue (myself included) that 65536 is impossible on a conforming
implementation (be that C90 or C99).


You would be right.

--
pete
Nov 14 '05 #18

P: n/a
Chris Torek <no****@torek.net> spoke thus:
Actually, this is potentially quite different. If ANSI/ISO C used the *correct* rules (according to me :-) )
it would be precisely the same, but we are stuck with quite
bogus widening rules due to a mistaken decision in the 1980s:
"when a narrow unsigned integer type widens, the resulting
type is signed if all the unsigned values fit, otherwise
it is unsigned". etc.


Wow, what a great article! The only thing I'm unclear on now is why
such a seemingly obvious point escaped the C89 people, and why you
weren't around to dissuade them ;)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #19

P: n/a
>Chris Torek <no****@torek.net> spoke thus:
If ANSI/ISO C used the *correct* rules (according to me :-) ) ...

In article <news:bs**********@chessie.cirr.com>
Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote:Wow, what a great article! The only thing I'm unclear on now is why
such a seemingly obvious point escaped the C89 people, and why you
weren't around to dissuade them ;)


I was but a poor student at the time (making about four bucks an
hour, with a limit of 20 hrs/week, as "student staff") and could
not afford exotic vacation trips to ANSI C committee meetings. :-)
I did, however, hear from someone who did go to them that this was
actually something of a "hotly debated" topic.

The VAX PCC did it "my" way, and apparently Plauger's C compiler(s)
did it the other way. The "base document" -- i.e., K&R-1 -- did
not even allow for the possibility of "unsigned short" and "unsigned
char", and if you have "narrow unsigned always widens to unsigned"
as a rule, you need an exception for plain char if/when plain char
is unsigned (as on the IBM 370), so that EOF can be negative.

The results of the rules differ only in "questionably signed" cases,
which are rare enough. But the ANSI rules are so ugly to work with
that I would prefer a special exception for "plain char is unsigned
on this implementation, yet nonetheless widens to signed int". Note
that this exception would force the constraint that CHAR_MAX < INT_MAX,
even when char is unsigned, which would have the happy side effect
of making stdio "work right".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #20

P: n/a
> If we have two "unsigned short"s, values 65535 and 3 respectively,
and go to add them, we continue to have "case a" and "case b".
In case (a), the sum is 65535U + 3U, which has type unsigned int
and value 2. In case (b), the sum is 65535 + 3, which has type
signed int and value 65538.


Just to make sure this is absolutely clear in my mind:
You are saying that the type of the expression
(unsigned short)65535 + (unsigned short)3
could be something other than "unsigned short" ?

Also, if we have
unsigned short a = 65535, b = 3;
then could the type of
(a + b)
not be "unsigned short" ?

This would be relevant to templates and/or function overloading, eg.
void f(unsigned int t) { /*...*/ }
void f(signed int t} { /*...*/ }

and you went: f((unsigned short)65535 + (unsigned short) 3)
or: f(65535u + 3u)
or, with the above declarations:
f(a+b) // might not even know till runtime
Finally, I had been taught that "65535u" means (unsigned int)65535
which is a whole different kettle of fish to (unsigned short)65535.
Is this correct?
Nov 14 '05 #21

P: n/a
"Old Wolf" <ol*****@inspire.net.nz> wrote in message
news:84**************************@posting.google.c om...
If we have two "unsigned short"s, values 65535 and 3 respectively,
and go to add them, we continue to have "case a" and "case b".
In case (a), the sum is 65535U + 3U, which has type unsigned int
and value 2. In case (b), the sum is 65535 + 3, which has type
signed int and value 65538.
Just to make sure this is absolutely clear in my mind:


You should get a good C book, or check out the Standard(s) or a draft like
N869.
You are saying that the type of the expression
(unsigned short)65535 + (unsigned short)3
could be something other than "unsigned short" ?
It _has_ to be.
Also, if we have
unsigned short a = 65535, b = 3;
then could the type of
(a + b)
not be "unsigned short" ?
The type of (a + b) will _never_ be unsigned short, since integer operands
of + are always subject to integral promotion.

Try the following program on an implementation where short and int have
different sizes:

#include <stdio.h>

int main(void)
{
unsigned short a = 65530;
unsigned short b = 3;

printf("%u\n", (unsigned) sizeof( a ));
printf("%u\n", (unsigned) sizeof( + a ));
printf("%u\n", (unsigned) sizeof( a + b ));

return 0;
}
This would be relevant to templates and/or function overloading, eg.
void f(unsigned int t) { /*...*/ }
void f(signed int t} { /*...*/ }
Ask a C++ group.
Finally, I had been taught that "65535u" means (unsigned int)65535
which is a whole different kettle of fish to (unsigned short)65535.
Is this correct?


Define 'kettle of fish'.

A singular u suffix means the constant (if valid) is an unsigned integral
type starting in rank from unsigned int, through the higher ranked standard
unsigned integers, then (for C99) suitable extended integer types(*). For
65535u, it's an unsigned int.

(*) It seems that constants larger than the standard integer type range need
not necessarily attain the lowest ranked eligible extended integer type.

--
Peter
Nov 14 '05 #22

P: n/a
"Peter Nilsson" <ai***@acay.com.au> wrote in message news:<3f******@news.rivernet.com.au>...
You are saying that the type of the expression
(unsigned short)65535 + (unsigned short)3
could be something other than "unsigned short" ?


It _has_ to be.
Also, if we have
unsigned short a = 65535, b = 3;
then could the type of
(a + b)
not be "unsigned short" ?


The type of (a + b) will _never_ be unsigned short, since integer operands
of + are always subject to integral promotion.


Yes, but if you assign the result to an unsigned short variable, then
the result will be truncated and is still unsigned short and you still have
modulus 2^n (n=bit size of unsigned short) arithmetic. Am I right? eg.

unsigned short i = (unsigned short)65535 + (unsigned short)3;

result of i is 2. Correct?

Andy
Nov 14 '05 #23

P: n/a
Andy wrote:

"Peter Nilsson" <ai***@acay.com.au> wrote in message news:<3f******@news.rivernet.com.au>...
You are saying that the type of the expression
(unsigned short)65535 + (unsigned short)3
could be something other than "unsigned short" ?


It _has_ to be.
Also, if we have
unsigned short a = 65535, b = 3;
then could the type of
(a + b)
not be "unsigned short" ?


The type of (a + b) will _never_ be unsigned short,
since integer operands
of + are always subject to integral promotion.


Yes, but if you assign the result to an unsigned short variable,
then the result will be truncated and is
still unsigned short and you still have
modulus 2^n (n=bit size of unsigned short) arithmetic.
Am I right? eg.

unsigned short i = (unsigned short)65535 + (unsigned short)3;

result of i is 2. Correct?


The cast operates on the constants.
The results of the casts, are the operands to the addition operator.
The operands of the addition operator are promoted to either
int or unsigned.
The right operand of the assignment operator
is converted to the type of the left.

If INT_MAX is 32767
then the operands will be promoted to unsigned.
If the result of the addition is greater than UINT_MAX
then the result will be reduced to 2,
otherwise the result of the addition will be 65538.

if INT_MAX is greater than 32767
then the operands will be promoted to int.
If the result of the addition is greater than INT_MAX,
then the behavior is undefined,
otherwise the result of the addition will be 65538.

If the result of the addition is greater than USHRT_MAX,
then i will be assigned a value of 2,
otherwise, i will be asigned the value of the result of the addition,
unless the addition caused undefined behavior.

--
pete
Nov 14 '05 #24

P: n/a
pete <pf*****@mindspring.com> wrote in message news:<3F***********@mindspring.com>...

if INT_MAX is greater than 32767
then the operands will be promoted to int.
If the result of the addition is greater than INT_MAX,
then the behavior is undefined,
otherwise the result of the addition will be 65538.

If the result of the addition is greater than USHRT_MAX,
then i will be assigned a value of 2,
otherwise, i will be asigned the value of the result of the addition,
unless the addition caused undefined behavior.


Can unsigned short be more than 2 bytes long? If not, then
(unsigned short)c1 + (unsigned short)c2 will never cause undefined
behavior because
1. If INT_MAX == USHRT_MAX, then c1 and c2 will be promoted
to unsigned short and unsigned short additions will never
cause undefined behaviors.
2. If INT_MAX > USHRT_MAX, then c1 and c2 will be promoted to
int, but c1+c2 is always <= 2*65535 so the addition can
never overflow because INT_MAX is >= 4 bytes.

So then is correct to say that (unsigned short)c1 + (unsigned short)c2
will never cause undefined behaviors? The reason is because in the
book "C, Traps and Pitfalls", the author states that unsigned arithmetic
shall always be done modulus 2^n manner where n is the number of bits
for the unsigned variable. But the edition I got is old (~1991) and
predates the ANSI standard. How about (unsigned long)c1 + (unsigned long)c2?

Andy
Nov 14 '05 #25

P: n/a
Andy wrote:
pete <pf*****@mindspring.com> wrote in message
news:<3F***********@mindspring.com>...
> if INT_MAX is greater than 32767
then the operands will be promoted to int.
If the result of the addition is greater than INT_MAX,
then the behavior is undefined,
otherwise the result of the addition will be 65538.

If the result of the addition is greater than USHRT_MAX,
then i will be assigned a value of 2,
otherwise, i will be asigned the value of the result of the addition,
unless the addition caused undefined behavior.


Can unsigned short be more than 2 bytes long?


Yes. On a Cray, for example, it might easily be eight bytes long.

<snip>
book "C, Traps and Pitfalls", the author states that unsigned arithmetic
shall always be done modulus 2^n manner where n is the number of bits
for the unsigned variable. But the edition I got is old (~1991) and
predates the ANSI standard.


The ANSI Standard dates from 1989. The author's statement is, however,
correct.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #26

P: n/a
Andy wrote:

pete <pf*****@mindspring.com> wrote in message news:<3F***********@mindspring.com>...
if INT_MAX is greater than 32767
then the operands will be promoted to int.
If the result of the addition is greater than INT_MAX,
then the behavior is undefined,
otherwise the result of the addition will be 65538.

If the result of the addition is greater than USHRT_MAX,
then i will be assigned a value of 2,
otherwise,
i will be asigned the value of the result of the addition,
unless the addition caused undefined behavior.


Can unsigned short be more than 2 bytes long? If not, then
(unsigned short)c1 + (unsigned short)c2 will never cause undefined
behavior because
1. If INT_MAX == USHRT_MAX, then c1 and c2 will be promoted
to unsigned short and unsigned short additions will never
cause undefined behaviors.


Nothing ever gets promoted to unsigned short.
"the integer promotions" are either to int or to unsigned int.

N869
6.3.1 Arithmetic operands
6.3.1.1 Boolean, characters, and integers
[#2]
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. These are called the integer
promotions.
2. If INT_MAX > USHRT_MAX, then c1 and c2 will be promoted to
int, but c1+c2 is always <= 2*65535 so the addition can
never overflow because INT_MAX is >= 4 bytes.

So then is correct to say that
(unsigned short)c1 + (unsigned short)c2
will never cause undefined behaviors?
No.
The reason is because in the
book "C, Traps and Pitfalls",
the author states that unsigned arithmetic
shall always be done modulus 2^n manner where n is the number of bits
for the unsigned variable. But the edition I got is old (~1991) and
predates the ANSI standard.
The problem is that you don't know
if the operands to the addition operator above, are unsigned.
How about (unsigned long)c1 + (unsigned long)c2?


The operands of the addition operator above, are unsigned types
which are not subject to the integer promotions,
so it's OK.

--
pete
Nov 14 '05 #27

P: n/a
"Andy" <bi*****@hotmail.com> wrote in message
news:ae**************************@posting.google.c om...
....
Can unsigned short be more than 2 bytes long?
Yes. The only _size_ criteria is that sizeof(short) >= 1. Of course, it has
to satisfy the minimum range requirement [0..65535], so the size of a short
(and therefore unsigned short) must be at least 16 bits. But since CHAR_BIT
may be anything >= 8, like 16 or 32 (e.g. DSP chipsets often have
implementations where CHAR_BIT is 32), it is possible for sizeof(short) to
be 1.

Theoretically, sizeof(short) > sizeof(long) is allowed in a conforming
implementation without contradiction.

Basically, the byte size of unsigned short is totally irrelevent to the
issue. The semantics of C integer expressions are defined by type and value,
not by the size of the representations.

You would do well to avoid forming preconceptions about the size of various
integer types. Not because there are theoretical possibilities, but because
there are very real practical problems that can result as a consequence.
E.g., when the world went from 16 to 32-bit home computers an awful lot of
poor code had to be painstakingly rewritten. Now that we sit on the edge of
64-bit machines becoming the 'norm', you should appreciate that making
assumptions about integer sizes may cost you (or the people who have to
maintain your code) in a few years time.
If not, then
(unsigned short)c1 + (unsigned short)c2 will never cause undefined
behavior because
1. If INT_MAX == USHRT_MAX, then c1 and c2 will be promoted
to unsigned short and unsigned short additions will never
cause undefined behaviors.
INT_MAX == USHRT_MAX is extremely unlikely[*], but in such a case, the
operands of + will both be promoted to int since all the values of unsigned
short _are_ representable as an int. The promotion to int applies to the
operands, which in this case are...

(unsigned short) c1 and (unsigned short) c2

A cast will not _override_ integral promotion.
2. If INT_MAX > USHRT_MAX, then c1 and c2 will be promoted to
int, but c1+c2 is always <= 2*65535
Strictly speaking, in this case, the sum of two unsigned short values is
always less than or equal to 2*USHRT_MAX+1.
so the addition can
never overflow because INT_MAX is >= 4 bytes.
There is nothing in the standards that state that an int must be twice the
size of an unsigned short. There are plenty of implementations where short
and int have the same properties except for their 'rank'.
So then is correct to say that (unsigned short)c1 + (unsigned short)c2
will never cause undefined behaviors? The reason is because in the
book "C, Traps and Pitfalls", the author states that unsigned arithmetic
shall always be done modulus 2^n manner where n is the number of bits
for the unsigned variable.
Yes, but you have to be careful to assertain whether the arithmetic is
indeed being performed on unsigned operands. In the case of adding two
unsigned short values, that isn't a given.
But the edition I got is old (~1991) and
predates the ANSI standard.
I've never read the book, but what it says is true. What the author may not
have known at the time of original writing was whether unsigned short would
possibly promote to int, instead of always promoting to unsigned int. [This
was apparently contested by the C committee.]
How about (unsigned long)c1 + (unsigned long)c2?


The two operands have type unsigned long and are therefore not subject to
integral promotion, nor indeed any other promotion. So the result is an
unsigned long calculated modulo ULONG_MAX+1.
[*] C90 apparently has no concept of padded integers or integer trap
representations, so you're not likely to find a conforming C implementation
where INT_MAX == USHRT_MAX any time soon. It's possible in C99, but I doubt
anyone will ever actually build such an implementation. [It would be
possible on a machine which used floating point instructions to mimic
integer calculations, but such a machine would probably have a hard time
implementing unsigned integer types as a whole, so the compiler writers
would probably give it up as a bad job. ;)]

--
Peter
Nov 14 '05 #28

P: n/a
"Andy" <bi*****@hotmail.com> wrote in message
news:ae**************************@posting.google.c om...
"Peter Nilsson" <ai***@acay.com.au> wrote in message news:<3f******@news.rivernet.com.au>...
You are saying that the type of the expression
(unsigned short)65535 + (unsigned short)3
could be something other than "unsigned short" ?


It _has_ to be.
Also, if we have
unsigned short a = 65535, b = 3;
then could the type of
(a + b)
not be "unsigned short" ?


The type of (a + b) will _never_ be unsigned short, since integer operands of + are always subject to integral promotion.


Yes, but if you assign the result to an unsigned short variable, then
the result will be truncated and is still unsigned short and you still

have modulus 2^n (n=bit size of unsigned short) arithmetic. Am I right?
Yes, but only assuming the value to be assigned can itself be computed
without undefined behaviour.
eg.

unsigned short i = (unsigned short)65535 + (unsigned short)3;

result of i is 2. Correct?


Not necessarily. Even after casting, the operands of + are _still_ subject
to integral promotion. So, the expression is effectively...

#if USHRT_MAX <= INT_MAX

unsigned short i = (int) (unsigned short) 65535 + (int) (unsigned short)
3;

#else

unsigned short i = (unsigned) (unsigned short) 65535 + (unsigned)
(unsigned short) 3;

#endif

It's highly unlikely, but it is possible for INT_MAX to equal USHRT_MAX, in
which case, the addition may overflow an int, invoking undefined behaviour.

--
Peter
Nov 14 '05 #29

P: n/a
"Peter Nilsson" <ai***@acay.com.au> wrote in message news:<3f********@news.rivernet.com.au>...

#if USHRT_MAX <= INT_MAX

unsigned short i = (int) (unsigned short) 65535 + (int) (unsigned short)
3;

#else

unsigned short i = (unsigned) (unsigned short) 65535 + (unsigned)
(unsigned short) 3;

#endif

It's highly unlikely, but it is possible for INT_MAX to equal USHRT_MAX, in
which case, the addition may overflow an int, invoking undefined behaviour.


Yes. I got it now. Thanks for clearing things up with the <=
point. I guess, then I can say that unsigned short
addition/subtraction on a machine where sizeof(unsigned short) ==
sizeof(int) will always yield valid modulus 2^n results. Correct?

Thanks
Andy
Nov 14 '05 #30

P: n/a
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<bs**********@sparta.btinternet.com>...
Andy wrote:

Can unsigned short be more than 2 bytes long?


Yes. On a Cray, for example, it might easily be eight bytes long.


Really? From my 1st day at work, I've been taught that
unsigned short is always 2 bytes long while int is variable in length.
You learn something everyday.

Thanks
Andy
Nov 14 '05 #31

P: n/a
bi*****@hotmail.com (Andy) writes:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<bs**********@sparta.btinternet.com>...
Andy wrote:

Can unsigned short be more than 2 bytes long?


Yes. On a Cray, for example, it might easily be eight bytes long.


Really? From my 1st day at work, I've been taught that
unsigned short is always 2 bytes long while int is variable in length.


Interesting. `unsigned short' is commonly 2 bytes in size, and 2
bytes is commonly 16 bits, but neither is required. 16 bits is
the minimum size of an `unsigned short', though.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 14 '05 #32

P: n/a
Andy wrote:
Richard Heathfield wrote:
Andy wrote:
> Can unsigned short be more than 2 bytes long?


Yes. On a Cray, for example, it might easily be eight bytes long.


Really? From my 1st day at work, I've been taught that
unsigned short is always 2 bytes long while int is variable in length.
You learn something everyday.


Here's another one for your collection of strange facts. On a 32-bit DSP,
you might easily find that unsigned short is just *one* byte long (that
byte being 32 bits wide, of course).

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #33

P: n/a
In article <news:ae**************************@posting.google. com>
Andy <bi*****@hotmail.com> writes:
... I guess, then I can say that unsigned short
addition/subtraction on a machine where sizeof(unsigned short) ==
sizeof(int) will always yield valid modulus 2^n results. Correct?


Well, C99 allows for "padding bits" in various representations, in
which case it is possible (though bizarre) to have, e.g.,
CHAR_BIT = 9, sizeof(short) = sizeof(unsigned short) = 2, and
sizeof(int) = 2; yet INT_MAX could be 131071 (no padding bits)
while USHRT_MAX is 65535 (two padding bits). In this case, since
USHRT_MAX < INT_MAX, "unsigned short" promotes to (signed) int
under the ANSI/ISO widening rules!

Such an implementation is certainly bizarre, but it appears to meet
the Standard's requirements.

Note that unless an implementation is *really* strange, we either
have USHRT_MAX > INT_MAX (e.g., 16-bit PDP-11), or 2*USHRT_MAX <=
INT_MAX (e.g., 16-bit "short", 32-bit "int" systems). If the first
is true -- if USHRT_MAX exceeds INT_MAX -- then unsigned short
promotes to unsigned int and arithmetic works mod 2**n. Otherwise,
double USHRT_MAX is still a valid "int" value, so the sum of any
two unsigned short values after they are promoted to signed int
values is a valid, nonnegative "int" value. For instance,
65535 + 65535 is 131070, and on 18-bit-or-more machines this should
be strictly less than INT_MAX (131071 or more). Of course, the
difference (subtraction) of two such values can be a negative "int",
and the sum of three or more such values can overflow.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #34

P: n/a
On Tue, 30 Dec 2003 20:37:08 -0800, Andy wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<bs**********@sparta.btinternet.com>...
Andy wrote:
>
> Can unsigned short be more than 2 bytes long?


Yes. On a Cray, for example, it might easily be eight bytes long.


Really? From my 1st day at work, I've been taught that
unsigned short is always 2 bytes long while int is variable in length.
You learn something everyday.


Y'all been taught wrong. Types in C and C++ (apart from the new
specified-size types in C99) are defined by minimum required ranges (and
the caveat that some types must be as large or larger than others).

Net result: an unsigned can be one byte, or 128 bytes, as long as it
handles _at least_ the minimum required range.
Nov 14 '05 #35

This discussion thread is closed

Replies have been disabled for this discussion.