473,756 Members | 5,850 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

itoa in pure C

I wrote a version of itoa yesterday.

Features:
1 No implementation defined arithmetic. All of the division
and modulus division is done on positive values only.
2 No object is assumed capable of representing the
magnitude of INT_MIN.
3 The string is constructed in place without reversal.
4 No features from standard library are used.

sput_i writes the decimal representation of a nonnegative int value
argument to an array of char.
sput_ip1 writes the representation of one greater than the
argument value, for any nonnegative int value argument, to an
array of char.

/* BEGIN itoa.c */

void itoa(int, char *);
char *sput_i(int, char *);
char *sput_ip1(int, char *);

void itoa(int integer, char *string)
{
if (0 > integer) {
++integer;
*string++ = '-';
*sput_ip1(-integer, string) = '\0';
} else {
*sput_i(integer , string) = '\0';
}
}

char *sput_i(int integer, char *string)
{
if (integer / 10 != 0) {
string = sput_i(integer / 10, string);
}
*string++ = (char)('0' + integer % 10);
return string;
}

char *sput_ip1(int integer, char *string)
{
int digit;

digit = (integer % 10 + 1) % 10;
if (integer / 10 != 0) {
string = (digit == 0 ? sput_ip1 : sput_i)(integer / 10, string);
*string++ = (char)('0' + digit);
} else {
if (digit == 0) {
*string++ = '1';
}
*string++ = (char)('0' + digit);
}
return string;
}

/* END itoa.c */

--
pete
Nov 14 '05 #1
29 20903
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
I wrote a version of itoa yesterday.

Features:
1 No implementation defined arithmetic.
All of the division
and modulus division is done on positive values only.
Why is that important? If you want _maximum_ compiler optimisation
potential, then you should make sput_i take an unsigned argument as
not all compilers will recognise that the supplied integer will
always be non-negative.
2 No object is assumed capable of representing the
magnitude of INT_MIN.
But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int. James Kuyper has argued in csc that this
need not be true in C99.

So, [-1000000..33000] would be a valid range for int!

I would like the Committee to formally disallow this as it makes
statements like i |= 1 potential UB even if i is positive. Also, it
makes division of two arbitrarily signed integers highly problematic.
3 The string is constructed in place without reversal.
Why is this important? [Have you profiled the cost of recursion
against an iterative reversing of the string?]
4 No features from standard library are used.

<snip>

What are your thoughts on...?

char *itoa(int i, char *s)
{
char *p = s;
char *q = s;

if (i >= 0)
{
do
{
*q++ = '0' + (i % 10);
}
while (i /= 10);
}
else if (-1 % 2 < 0)
{
*q++ = '-';
p++;

do
{
*q++ = '0' - i % 10;
}
while (i /= 10);
}
else
{
*q++ = '-';
p++;

do
{
int d = i % 10;
i = i / 10;
if (d) { i++; d = 10 - d; }
*q++ = '0' + d;
}
while (i);
}

for (*q = 0; p < --q; p++)
{
char c = *p;
*p = *q;
*q = c;
}

return s;
}

--
Peter
Nov 14 '05 #2
Peter Nilsson wrote:

"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
I wrote a version of itoa yesterday.

Features:
1 No implementation defined arithmetic.
All of the division
and modulus division is done on positive values only.
Why is that important?


I've seen posted versions with implementation defined behavior.
If you want _maximum_ compiler optimisation
potential, then you should make sput_i take an unsigned argument as
not all compilers will recognise that the supplied integer will
always be non-negative.
It should be unsigned. I used int as a "nothing up my sleeves"
gesture, to emphasize that the magnitude of INT_MIN
wasn't be represented by an integer type.
2 No object is assumed capable of representing the
magnitude of INT_MIN.


But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int.
James Kuyper has argued in csc that this need not be true in C99.


Well, ... I'm guessing he was arguing with other smart people too.

So, [-1000000..33000] would be a valid range for int!

I would like the Committee to formally disallow this as it makes
statements like i |= 1 potential UB even if i is positive. Also, it
makes division of two arbitrarily signed integers highly problematic.
3 The string is constructed in place without reversal.


Why is this important?


It's a novelty feature.
I don't think anybody was waiting for a new itoa.
4 No features from standard library are used.

<snip>

What are your thoughts on...?

char *itoa(int i, char *s)
{
char *p = s;
char *q = s;

if (i >= 0)
{
do
{
*q++ = '0' + (i % 10);
}
while (i /= 10);
}
else if (-1 % 2 < 0)
{
*q++ = '-';
p++;

do
{
*q++ = '0' - i % 10;
}
while (i /= 10);
}
else
{
*q++ = '-';
p++;

do
{
int d = i % 10;
i = i / 10;
if (d) { i++; d = 10 - d; }
*q++ = '0' + d;
}
while (i);
}

for (*q = 0; p < --q; p++)
{
char c = *p;
*p = *q;
*q = c;
}

return s;
}


At first glance, it seems to be efficient and thorough.
I'll take a closer look at it.

--
pete
Nov 14 '05 #3
On Mon, 26 Jan 2004 11:41:28 +1100, "Peter Nilsson"
<ai***@acay.com .au> wrote in comp.lang.c:
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
I wrote a version of itoa yesterday.

Features:
1 No implementation defined arithmetic.
All of the division
and modulus division is done on positive values only.
Why is that important? If you want _maximum_ compiler optimisation
potential, then you should make sput_i take an unsigned argument as
not all compilers will recognise that the supplied integer will
always be non-negative.
2 No object is assumed capable of representing the
magnitude of INT_MIN.


But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int. James Kuyper has argued in csc that this
need not be true in C99.


INT_MIN + 1 is certainly representable in a signed int. So is
-(INT_MIN + 1). Either you have misunderstood James' arguments, or he
is just plain wrong.
So, [-1000000..33000] would be a valid range for int!
No, it is not. INT_MAX must be some power of 2 minus 1. INT_MIN must
either be -INT_MAX, or -INT_MAX - 1. There is no combination of value
bits that is invalid in an unsigned integer type or in a positive
signed integer type.

There are only two possible combinations of sign and value bits that
might be trap representations for signed integer types, and only one
for each of the allowed types of representation. For signed magnitude
and 2's complement, that is the bit combination of the sign bits 0 and
all value bits 1. For 1's complement, it is the sign bit 1 and all
value bits 1.

Assuming that the value and sign bits do not have the one possible
invalid value for the representation, the only way to have a trap
value in a signed integer type is if there is some invalid combination
of padding bits.

6.6.2 makes this all quite clear.
I would like the Committee to formally disallow this as it makes
statements like i |= 1 potential UB even if i is positive. Also, it
makes division of two arbitrarily signed integers highly problematic.


This does make it possible for i |= 1 to produce undefined behavior on
1's complement implementations , specifically if the prior value of i
had the sign bit and all but the least significant value bit set to 1
prior to the operation, it could produce a trap representation.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #4
"Jack Klein" <ja*******@spam cop.net> wrote in message
news:e2******** *************** *********@4ax.c om...
On Mon, 26 Jan 2004 11:41:28 +1100, "Peter Nilsson"
<ai***@acay.com .au> wrote in comp.lang.c:
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
I wrote a version of itoa yesterday.

Features: <snip> 2 No object is assumed capable of representing the
magnitude of INT_MIN.
But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int. James Kuyper has argued in csc that this
need not be true in C99.


INT_MIN + 1 is certainly representable in a signed int. So is
-(INT_MIN + 1). Either you have misunderstood James' arguments, or he
is just plain wrong.


Well I guess you choose the latter. Here's one thread in which he discusses
this...

http://groups.google.com/groups?thre...2%40wizard.net

<snip> 6.6.2 makes this all quite clear.


ITYM 6.2.6, but see the link above.

--
Peter
Nov 14 '05 #5
Peter Nilsson wrote:

"Jack Klein" <ja*******@spam cop.net> wrote in message
news:e2******** *************** *********@4ax.c om...
On Mon, 26 Jan 2004 11:41:28 +1100, "Peter Nilsson"
<ai***@acay.com .au> wrote in comp.lang.c:
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
> I wrote a version of itoa yesterday.
>
> Features: <snip> > 2 No object is assumed capable of representing the
> magnitude of INT_MIN.

But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int. James Kuyper has argued in csc that this
need not be true in C99.


INT_MIN + 1 is certainly representable in a signed int. So is
-(INT_MIN + 1). Either you have misunderstood James' arguments, or he
is just plain wrong.


Well I guess you choose the latter. Here's one thread in which he discusses
this...

http://groups.google.com/groups?thre...2%40wizard.net

<snip>
6.6.2 makes this all quite clear.


ITYM 6.2.6, but see the link above.


The matter of how many value bits are in the unsigned type,
is irrelevant.
The signed type has the same number of value bits as itself,
regardless of whether it's representing a positive or negative value.

--
pete
Nov 14 '05 #6
On Mon, 26 Jan 2004 15:24:56 +1100, "Peter Nilsson"
<ai***@acay.com .au> wrote in comp.lang.c:
"Jack Klein" <ja*******@spam cop.net> wrote in message
news:e2******** *************** *********@4ax.c om...
On Mon, 26 Jan 2004 11:41:28 +1100, "Peter Nilsson"
<ai***@acay.com .au> wrote in comp.lang.c:
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
> I wrote a version of itoa yesterday.
>
> Features: <snip> > 2 No object is assumed capable of representing the
> magnitude of INT_MIN.

But you do assume that the magnitude of INT_MIN+1 (and others) _are_
representable within an int. James Kuyper has argued in csc that this
need not be true in C99.


INT_MIN + 1 is certainly representable in a signed int. So is
-(INT_MIN + 1). Either you have misunderstood James' arguments, or he
is just plain wrong.


Well I guess you choose the latter. Here's one thread in which he discusses
this...

http://groups.google.com/groups?thre...2%40wizard.net

<snip>
6.6.2 makes this all quite clear.


ITYM 6.2.6, but see the link above.


Yes, I've seen the thread, and it is hair-splitting nonsense.

Paragraph 5 of 6.2.6.1:

<quote>
Certain object representations need not represent a value of the
object type. If the stored value of an object has such a
representation and is read by an lvalue expression that does
not have character type, the behavior is undefined. If such a
representation is produced by a side effect that modifies all or any
part of the object by an lvalue expression that does not have
character type, the behavior is undefined. Such a representation is
called a trap representation.
<unquote>

The contents of an object referenced by an lvalue of a particular type
(other than unsigned char) can be one of two things: a value or a
trap representation. It can't be both, it can't be neither.

Then there are paragraphs 1 & 2 of 6.2.6.2:

<quote>
1 For unsigned integer types other than unsigned char, the bits of the
object representation shall be divided into two groups: value bits and
padding bits (there need not be any of the latter). If there are N
value bits, each bit shall represent a different power of 2 between 1
and 2N-1, so that objects of that type shall be capable of
representing values from 0 to 2N - 1 using a pure binary
representation; this shall be known as the value representation. The
values of any padding bits are unspecified.

2 For signed integer types, the bits of the object representation
shall be divided into three groups: value bits, padding bits, and the
sign bit. There need not be any padding bits; there shall be exactly
one sign bit. Each bit that is a value bit shall have the same value
as the same bit in the object representation of the corresponding
unsigned type (if there are M value bits in the signed type and N in
the unsigned type, then M <= N). If the sign bit
is zero, it shall not affect the resulting value. If the sign bit is
one, the value shall be modified in one of the following ways:

— the corresponding value with sign bit 0 is negated (sign and
magnitude);

— the sign bit has the value -(2N) (two’s complement);

— the sign bit has the value -(2N - 1) (one’s complement).

Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero (for the first two), or
with sign bit and all value bits 1 (for one’s complement), is a trap
representation or a normal value. In the case of sign and magnitude
and one’s complement, if this representation is a normal value it is
called a negative zero.
<unquote>

Each value bit contributes to a value, and the sign bit, when set
specifically has a value that combines with the value of the value
bits.

When the standard provides a list of anything, in this case possible
combinations of sign and value bits that may be trap representations ,
without a qualifier like "includes", that list is exclusive. Nowhere
in the standard does it say that any other combinations of sign and
value bits may be trap representations and not values.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #7
In article <8c************ *************** *****@4ax.com>, Jack Klein wrote:

Then there are paragraphs 1 & 2 of 6.2.6.2:

<quote>
1 For unsigned integer types other than unsigned char, the bits of the
object representation shall be divided into two groups: value bits and
padding bits (there need not be any of the latter). If there are N
value bits, each bit shall represent a different power of 2 between 1
and 2N-1, so that objects of that type shall be capable of
representing values from 0 to 2N - 1 using a pure binary
representation; this shall be known as the value representation. The
values of any padding bits are unspecified.

2 For signed integer types, the bits of the object representation
shall be divided into three groups: value bits, padding bits, and the
sign bit. There need not be any padding bits; there shall be exactly
one sign bit. Each bit that is a value bit shall have the same value
as the same bit in the object representation of the corresponding
unsigned type (if there are M value bits in the signed type and N in
the unsigned type, then M <= N). If the sign bit
This has bearing on _my_ long-term troubling question about writing
an honestly portable itoa.

If I write (in the OTBS):

char *local_itoa(int i)
{
unsigned int x = (i>=0) ? (unsigned) i : -(unsigned) i;
....
am I guaranteed that the absolute value of i can be represented
in x? A literal reading of this standard would suggest not, if
M (the _data_bit_ width of signed int) is equal to N (the width
of unsigned int), and the input value is INT_MIN in twos-complement,
i.e., -(2^N). In that case the absolute value (-(unsigned)i) should
be 2^N, but the max value representable is 2^M-1. This possibility
is unique to architectures with twos-complement signed representations .

If the standard does not guarantee this, should it? Are there
any known twos-complement architectures where N==M? Are there
_any_ architectures where N==M, or did the standard writers glitch
and mean to write M < N?

Enquiring minds want to know. ;-)

- Larry
is zero, it shall not affect the resulting value. If the sign bit is
one, the value shall be modified in one of the following ways:

— the corresponding value with sign bit 0 is negated (sign and
magnitude);

— the sign bit has the value -(2N) (two’s complement);

— the sign bit has the value -(2N - 1) (one’s complement).

Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero (for the first two), or
with sign bit and all value bits 1 (for one’s complement), is a trap
representation or a normal value. In the case of sign and magnitude
and one’s complement, if this representation is a normal value it is
called a negative zero.
<unquote>

Nov 14 '05 #8
Larry Doolittle wrote:
Jack Klein wrote:

Then there are paragraphs 1 & 2 of 6.2.6.2:

<quote>
1 For unsigned integer types other than unsigned char, the bits
of the object representation shall be divided into two groups:
value bits and padding bits (there need not be any of the
latter). If there are N value bits, each bit shall represent a
different power of 2 between 1 and 2N-1, so that objects of
that type shall be capable of representing values from 0 to 2N
- 1 using a pure binary representation; this shall be known as
the value representation. The values of any padding bits are
unspecified.

2 For signed integer types, the bits of the object
representation shall be divided into three groups: value bits,
padding bits, and the sign bit. There need not be any padding
bits; there shall be exactly one sign bit. Each bit that is a
value bit shall have the same value as the same bit in the
object representation of the corresponding unsigned type (if
there are M value bits in the signed type and N in the
unsigned type, then M <= N). If the sign bit


This has bearing on _my_ long-term troubling question about writing
an honestly portable itoa.


What is the problem? Write a routine for an unsigned integer.
For integers, resolve the sign, convert to unsigned, and apply
that routine.

When you have languages that do not provide unsigned versions
things are slighly harder, because you have to allow for the fact
that negative values may have a larger range. In that case write
a routine to convert negative integers, ignoring the sign, and
then call that from a routine that handles the sign. This does
not apply to C.

--
Chuck F (cb********@yah oo.com) (cb********@wor ldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net> USE worldnet address!
Nov 14 '05 #9
CBFalconer wrote:

Larry Doolittle wrote:
Jack Klein wrote:

Then there are paragraphs 1 & 2 of 6.2.6.2:

<quote>
1 For unsigned integer types other than unsigned char, the bits
of the object representation shall be divided into two groups:
value bits and padding bits (there need not be any of the
latter). If there are N value bits, each bit shall represent a
different power of 2 between 1 and 2N-1, so that objects of
that type shall be capable of representing values from 0 to 2N
- 1 using a pure binary representation; this shall be known as
the value representation. The values of any padding bits are
unspecified.

2 For signed integer types, the bits of the object
representation shall be divided into three groups: value bits,
padding bits, and the sign bit. There need not be any padding
bits; there shall be exactly one sign bit. Each bit that is a
value bit shall have the same value as the same bit in the
object representation of the corresponding unsigned type (if
there are M value bits in the signed type and N in the
unsigned type, then M <= N). If the sign bit


This has bearing on _my_ long-term troubling question about writing
an honestly portable itoa.


What is the problem? Write a routine for an unsigned integer.
For integers, resolve the sign, convert to unsigned, and apply
that routine.


Can't do it if UINT_MAX == 65535, and INT_MIN == -65536.

CHAR_BIT == 16
INT_MAX == 65535
sizeof(unsigned ) == 2
sizeof(int) == 2

unsigned isn't guaranteed to be able to represent
the magnitude of INT_MIN.

--
pete
Nov 14 '05 #10

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

Similar topics

11
3707
by: John Lenton | last post by:
Is there any reason python's printf-style formatting is missing the (C99) '%a' specifier? I'm sorry if this has been asked and answered before; I can't find it on google ('%a' is a very awkward thing to look for): -- John Lenton (john@grulic.org.ar) -- Random fortune: Los cementerios están llenos de valientes.
7
12856
by: news.hku.hk | last post by:
Excuse me, i write the following function to add comma for integers but the unix server said: In function `class string comma(int)': implicit declaration of function `int itoa(...)' ________________________________ string comma(int a){ char to_string; string s_a = itoa(a, to_string, 10);
4
14338
by: Moritz Beller | last post by:
Hello! Is there an equivalent to Visual C++'s itoa function in gcc? best regards Moritz Beller -- web http://www.4momo.de mail momo dot beller at t-online dot de gpgkey http://gpg.notlong.com
2
5030
by: Raskolnikow | last post by:
Hi! I have a very simple problem with itoa() or the localtime(...). Sorry, if it is too simple, I don't have a proper example. Please have a look at the comments. struct tm *systime; time_t currentTime; char day; char month;
2
6678
by: Sona | last post by:
Hi, I have a char* that holds an ascii character in its first element (at least I think that's what it holds because when I print it, it prints weird characters). I need to convert this into an integer and so I thought the following might work: char *somevar ... // somevar holds a value in somevar and is null terminated i.e. somevar = '\0'
11
3603
by: rayw | last post by:
I'm pretty new to C, although I did do some years ago now. I've been told that itoa is no longer a standard function, and that the ato... functions - although in the std - are not recommended. So, I was wondering what was wrong with both itoa and atoi etc (and what's replaced them). Many thanks
24
8200
by: Mark | last post by:
hi, all i want is a simple function that takes an int, and returns a char* so i tried char * itoa(int i) { char buff; return _itoa(i,buff,10); }
7
39553
by: silverburgh.meryl | last post by:
Hi, Can you please tell me where I can find itoa()? I try to compile the following example, but I get the following error: .../t.cpp:20:2: warning: no newline at end of file .../t.cpp: In function 'int main()': .../t.cpp:13: error: 'itoa' was not declared in this scope /* itoa example */
0
9454
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
9271
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10028
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...
1
9836
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9707
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
8709
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...
0
6533
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
5139
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...
1
3804
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

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.