473,882 Members | 1,688 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

unsigned short addition/subtraction overflow

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
34 16711
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
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
On 2003-12-21, pete <pf*****@mindsp ring.com> wrote:
James Hu wrote:

On 2003-12-21, Andy <bi*****@hotmai l.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
>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.n ews.pas.earthli nk.net>
Kevin Goodsell <us************ *********@never box.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 "questionab ly 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 "predictabl y
surprising" than "unpredicta bly 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 "questionab ly 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 (40°39.22'N, 111°50.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
Chris Torek wrote:
In article <vC************ ***@newsread2.n ews.pas.earthli nk.net>
Kevin Goodsell <us************ *********@never box.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
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
pete <pf*****@mindsp ring.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
Peter Nilsson wrote:

pete <pf*****@mindsp ring.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
Chris Torek <no****@torek.n et> 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)cybers pace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #19
>Chris Torek <no****@torek.n et> spoke thus:
If ANSI/ISO C used the *correct* rules (according to me :-) ) ...

In article <news:bs******* ***@chessie.cir r.com>
Christopher Benson-Manica <at***@nospam.c yberspace.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 "questionab ly 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 (40°39.22'N, 111°50.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

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

Similar topics

96
4012
by: John Harrison | last post by:
I knew that unsigned integral data types were the cause of scads of mostly spurious warning messages, but I didn't realise that they were a security risk too (see here http://www.securitytracker.com/alerts/2004/Feb/1009067.html). All for one measly extra bit. So has the time come for C++ to deprecate unsigned integral types? john
49
5926
by: Neil Zanella | last post by:
Hello, Often I happen to be dealing with nonnegative integers and since I know I won't need negative numbers here I declare them as unsigned simply to make the program somewhat clearer. Effectively, though, signed integers would often work too since unless I am doing some modular arithmetic modulo the word length then I almost never need to use the high bit since the integers I deal with are usually not that large, and I would assume...
20
5378
by: Hanzac Chen | last post by:
Hi, I don't understand why this could happen? The Code 1 will output `fff9' and the Code 2 will output `1' How could the `mod 8' not have effect? /* Code 1 */ #include <stdio.h> #include <stdlib.h>
3
4597
by: linq936 | last post by:
I have some algorithm dealing with unsigned int calculation a lot, I am trying to add some check for overflow. The initial thinking was very easy, just do something like this, int addition(unsigned int i1, unsigned int i2) { if ( i1 + i2 < i1 || i1 + i2 < i2 ) { ...throw some expception... } return i1+i2; }
0
9932
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11109
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10405
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9558
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7957
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7114
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5782
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5979
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
3226
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.