473,394 Members | 1,717 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Can a "value" overflow?

Hello, can anyone explain why the following function will not work for
INT_MIN:
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;

if((sign = n) < 0) /* record sign */
n = -n; /* make n positive */

i = 0;
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s); /* another function; irrelevant to my question */
}

I've narrowed it down to the n = -n line. On my machine, -(INT_MIN)
would be 1 more than INT_MAX. Does this overflow the temporary value
-n, or the actual object n. What I'm trying to ask is, when the fault
happens?

My feeling is that the fault (undefined behaviour) first occurs with
the -n, because the value of the result is a signed int (no promotions
or conversions) and that value is overflowed. Does that make sense?
Can a "value" overflow just like objects can?

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?

Nov 14 '05 #1
14 2045
TTroy wrote:
Hello, can anyone explain why the following function will not work for INT_MIN:
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;

if((sign = n) < 0) /* record sign */
n = -n; /* make n positive */

i = 0;
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s); /* another function; irrelevant to my question */
}

I've narrowed it down to the n = -n line. On my machine, -(INT_MIN)
would be 1 more than INT_MAX. Does this overflow the temporary value
-n, or the actual object n. What I'm trying to ask is, when the fault happens?

My feeling is that the fault (undefined behaviour) first occurs with
the -n, because the value of the result is a signed int (no promotions or conversions) and that value is overflowed. Does that make sense?
Can a "value" overflow just like objects can?

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?


Values have types too. So the -n is a an expression that resolves to a
value of type signed int. You are overflowing the maximum capacity of
that type by 1, thus undefined behaviour.

Try this:

void itoa(int n, char s[]) {
int i, sign;
sign = n;

i = 0;
do {
s[i++] = abs(n % 10) + '0';
} while ( n /= 10 );
if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s);
}

In the example above, there are no overflows. I still think there is
an issue, though most computers will behave properly: the result of n %
10 is implementation defined because n could be negative (but any sane
compiler will produce the result most people expect)

Results like -18 % 10 = 8 are expected on any good implementation.

Nov 14 '05 #2
TTroy wrote:
Hello, can anyone explain why the following function will not work for INT_MIN:

-- Snip itoa() from KnR2, pg 64. --
I've narrowed it down to the n = -n line. On my machine, -(INT_MIN)
would be 1 more than INT_MAX. Does this overflow the temporary value
-n, or the actual object n. What I'm trying to ask is, when the fault happens?

My feeling is that the fault (undefined behaviour) first occurs with
the -n, because the value of the result is a signed int (no promotions or conversions) and that value is overflowed. Does that make sense?
Can a "value" overflow just like objects can?

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?
Isn't this straight out of KnR2, Exercise 3-4?

Basically, you're right, in two's complement, the absolute value of
INT_MIN is one greater than INT_MAX. Therefore, setting int i = INT_MIN
* -1; results in overflow (in two's complement).

In the itoa function above,
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
runs once, and then the while loop ends because n is still negative
because of the overflow.
The '-' is added:
if (sign < 0)
s[i++] = '-';

and then the string is terminated and reversed.
There are many ways to write this function, you just have to catch the
case of INT_MIN, either explicitly, e.g.:

if(n == INT_MIN) /* do something to prevent overflow */

or implicitly in a way that converts the INT_MIN into something safe to
assign into an integer.

Nov 14 '05 #3
Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?


You'll probably have to generate a special exception for INT_MIN, or
modify your algorithm.

The overflow happens to the value itself, so you can't save it by using
it before storing it in a variable (I think that was what you were asking).

However, a better method would probably be to not take the absolute
value. Just use it as a negative, and change your while to be

while((n /= 10) != 0)

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Nov 14 '05 #4
TTroy wrote:
void itoa(int n, char s[])


Others have addressed your specific question. I'd like to point out
that this is a poorly designed interface. You almost certainly want
to do something like:

void itoa(int n, char s[], size_t size)

--
================================================== ======================
Ian Pilcher i.*******@comcast.net
================================================== ======================
Nov 14 '05 #5
Ian Pilcher wrote:

TTroy wrote:
void itoa(int n, char s[])


Others have addressed your specific question. I'd like to point out
that this is a poorly designed interface. You almost certainly want
to do something like:

void itoa(int n, char s[], size_t size)

void itoa(int n, char s[]); is from K&R

--
pete
Nov 14 '05 #6
TTroy wrote:
Hello, can anyone explain why the following function will not work for INT_MIN:
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;

if((sign = n) < 0) /* record sign */
n = -n; /* make n positive */

i = 0;
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s); /* another function; irrelevant to my question */
}

I've narrowed it down to the n = -n line. On my machine, -(INT_MIN)
would be 1 more than INT_MAX. Does this overflow the temporary value
-n, or the actual object n. What I'm trying to ask is, when the fault happens?

My feeling is that the fault (undefined behaviour) first occurs with
the -n, because the value of the result is a signed int (no promotions or conversions) and that value is overflowed. Does that make sense?
Can a "value" overflow just like objects can?

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?


The value is overflowing like others have said. You have to check for
n == INT_MIN and deal with it accordingly

Here is a version of itoa I just coded, a couple tests show it's
rock-solid but there could be portability issues:
void itoa(int n, char *s)
{
int i = 0
int sign;

if((sign = n) == INT_MIN){ /* if n is overflow possible */
n = -(n + 10); /* add 1 to tens column then negate */
s[i++] = n % 10 + '0'; /* gets digit from ones column */
n = n/10 + 1; /* shifts out ones col then adds 1 */
}
else if(n < 0){ /* if n is not overflow possible */
n = -n; /* makes n positive */
}

do{
s[i++] = n % 10 + '0'; /* gets digit from ones column */
} while ((n /= 10) != 0); /* shifts out ones column */

if (sign < 0) /* if n was originally negative */
s[i++] = '-'; /* add negative sign to string */

s[i] = '\0'; /* adds NUL termination to string */
reverse(s); /* reverses string to proper form */
}
As others have said, if you intend to use a similar function in serious
programs or save it for reuse with multiplie programs, it's dangerous
to work on a string within a function without knowing how much room has
been allocated for it. You really should add a third parameter to the
function, so the caller can pass in the size of the string (at issue is
whether the size will include space for NUL or not).

Nov 14 '05 #7
davebsr wrote:
Basically, you're right, in two's complement, the absolute value of
INT_MIN is one greater than INT_MAX.
INT_MIN is allowed to be equal to -INT_MAX in two's complement.
if(n == INT_MIN) /* do something to prevent overflow */


(-INT_MAX > n) is the special case.

--
pete
Nov 14 '05 #8
> TTroy wrote:
void itoa(int n, char s[])

This has been done to death. Search the clc archives for...

"itoa in pure c"

Ian Pilcher wrote: Others have addressed your specific question. I'd like to point
out that this is a poorly designed interface. You almost certainly
want to do something like:

void itoa(int n, char s[], size_t size)


There is a limit on how big an int's decimal representation can be.
I'd prefer a slighter faster itoa that expects an appropriate buffer.
[C has never been a language for the faint hearted. ;-]

--
Peter

Nov 14 '05 #9
davebsr wrote:


Basically, you're right, in two's complement, the absolute value of
INT_MIN is one greater than INT_MAX. Therefore, setting int i = INT_MIN * -1; results in overflow (in two's complement).

In the itoa function above,
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
runs once, and then the while loop ends because n is still negative
because of the overflow.


Overflow causes undefined behaviour. You are 'assuming' that the
implementation just "wraps" numbers/bits like modular arithmetic and
allows the program to continue to assume that the bits held in the
signed integer is a valid/usable number.

The '-' is added:
if (sign < 0)
s[i++] = '-';

and then the string is terminated and reversed.
There are many ways to write this function, you just have to catch

the case of INT_MIN, either explicitly, e.g.:

if(n == INT_MIN) /* do something to prevent overflow */
yeap

or implicitly in a way that converts the INT_MIN into something safe to assign into an integer.


I'm not sure about that (can't think of an implicit method that works).

Nov 14 '05 #10
Romeo Colacitti wrote:
[snip]
I still think there is
an issue, though most computers will behave properly: the result of n %
10 is implementation defined because n could be negative (but any sane
compiler will produce the result most people expect)

Results like -18 % 10 = 8 are expected on any good implementation.


If anything, -18%10 == -8 or -18%10 == 2.
Either C standard makes it very clear what is to be expected:
If a/b is representable, then
(a/b)*b + a%b == a
The problem is what a/b gives you for either a or b negative.
C89 says it is implementation defined whether you get the next
larger or next smaller integer.
That is:
-18/10 -> -1, i.e. -1*10 + -18%10 == -18, i.e. -18%10 == -8
-18/10 -> -2, -2*10 + -18%10 == -18, -18%10 == 2

C99 explicitly demands truncation towards zero for a/b, i.e.
you will get -18%10 == -8.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #11
TTroy wrote:

Hello, can anyone explain why the following function will not work for
INT_MIN:

/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;

if((sign = n) < 0) /* record sign */
n = -n; /* make n positive */

i = 0;
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s); /* another function; irrelevant to my question */
}

I've narrowed it down to the n = -n line. On my machine, -(INT_MIN)
would be 1 more than INT_MAX. Does this overflow the temporary value
-n, or the actual object n. What I'm trying to ask is, when the fault
happens?

My feeling is that the fault (undefined behaviour) first occurs with
the -n, because the value of the result is a signed int (no promotions
or conversions) and that value is overflowed. Does that make sense?
Can a "value" overflow just like objects can?

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?


You can split off and handle INT_MIN separately, or make the
function use only negative values, or you can record the sign and
then convert to unsigned operands.

unsigned int v;

sign = (n < 0);
v = n;
/* do the rest using v in place of n */

however it is easier to have a master routine that converts
unsigned long, and to call it from the other conversion mechanisms
for other sizes. Maybe long long today.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #12
On Mon, 07 Feb 2005 14:46:32 -0800, Luke Wu wrote:

....
There are many ways to write this function, you just have to catch

the
case of INT_MIN, either explicitly, e.g.:

if(n == INT_MIN) /* do something to prevent overflow */


yeap


Although n < -INT_MAX is the more precise test. There's no need to execute
the special case code on platforms where INT_MIN == -INT_MAX, although it
does no harm.
or implicitly in a way that converts the INT_MIN into something safe

to
assign into an integer.


I'm not sure about that (can't think of an implicit method that works).


Well positive_n = -(type)n works if type is a signed or unsigned integer
type where -INT_MIN is representable. Even a floating point type would
work if it has full (exact) coverage of integers in the range. The problem
is finding suh a type portably.

Lawrence
Nov 14 '05 #13
pete wrote:
Ian Pilcher wrote:
TTroy wrote:
void itoa(int n, char s[])


Others have addressed your specific question. I'd like to point out
that this is a poorly designed interface. You almost certainly want
to do something like:

void itoa(int n, char s[], size_t size)


void itoa(int n, char s[]); is from K&R


I suppose that makes it holy writ? But I agree that it is wise for
the function to take a size. My belief is that any function that is
handed a pointer to a buffer that it is going to fill in should know how
big it is. Even itoa. If optimization shows that using the size is a
bottleneck (doubt it) well, you could ignore it in your actual
implementation. I've seen too much code like this:

char buf[12];
itoa(my_int, buf);

Surely 12 is big enough. Until we switch to a 64 bit ints, etc etc.

-David


Nov 14 '05 #14
"TTroy" <ti*****@gmail.com> writes:
[snip]
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;

if((sign = n) < 0) /* record sign */
n = -n; /* make n positive */

i = 0;
do /* generate digits in reverse order */
{
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';

s[i] = '\0';
reverse(s); /* another function; irrelevant to my question */
}

[snip]

Does anyone know how to fix this function to allow it to accept any
integer argument (including INT_MIN on 2's complement machines)?


The following function works in C99, and in ANSI C on implementations
that divide truncating towards zero:

void
itoa( const int n, char *s ){
static const char *digits = "9876543210123456789" + 9;
int t = n;
char *p = s;

do *p++ = digits[ t%10 ]; while( t /= 10 );
if( n < 0 ) *p++ = '-';
*p = 0;

reverse( s );
}
If you need something that works on implementations that divide
truncating towards minus infinity, try the following. I believe it
works on C89/C90 as long as '%' and '/' are appropriately in sync
(that is, (m/n)*n + m%n = m, whenever n != 0); but I've done
careful testing only with truncation towards zero and truncation
towards minus infinity.

void
more_general_itoa( const int n, char *s ){
static const char *digits = "9876543210987654321" + 9;
int r, t = n < 0 ? n : -n;
char *p = s;

do *p++ = digits[ r = t%10 ]; while( t = t/10 + (r > 0) );
if( n < 0 ) *p++ = '-';
*p = 0;

reverse( s );
}

Notice that the second function avoids problems with INT_MIN by
always switching to a *negative* representation.
Nov 14 '05 #15

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

Similar topics

9
by: Russ Perry Jr | last post by:
I'm using "ID" and "Value" in the generic sense here... Let's say one page I had a <html:select> with a collection like this: <html:options collection="items" property="key"...
2
by: Liang | last post by:
Hi, I use "defined $r_libs->{$name}" to check first if a key exists in a hash table. But Perl gives a warning WHENEVER the key exists: "Use of uninitialized value". Would u please help to...
5
by: johnsuth | last post by:
I want to produce a trivial demonstration of dynamic modification. I thought that pressing a button might change its color. I studied O'Reillys books and successfully created the button with a...
388
by: maniac | last post by:
Hey guys, I'm new here, just a simple question. I'm learning to Program in C, and I was recommended a book called, "Mastering C Pointers", just asking if any of you have read it, and if it's...
11
by: ajikoe | last post by:
Hello, I used Visual C# Standard Edition. I want to comment my program using xml commentary method, I don't know why if I use value and example tag, it is not working / showed in the html...
2
by: IkBenHet | last post by:
Hello, I am uploading a file using this form in ASP.NET. I have also added a simpel textfield: <form runat="server" enctype="multipart/form-data"> <input type="file" id="oFile" Name="oFile"...
2
by: Boki | last post by:
Hi All, // code start alert("document.all.txtbox"+valueA+".value") // end code could you please advice, can it show the value of txtbox ?
5
by: Diwa | last post by:
Does the "value" type (value as in key-value pair )of "std::map" require a default ctor even if it is not used ? If I comment out Line 1 in the code attached later, i.e remove the default ctor...
1
by: mark | last post by:
Forgive me if this seems like a stupid question but I need help... I'm trying to do a simple online form that emails me the results from a few fields. Here is the code: <form...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
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...

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.