itoa on the mac

2341 views
Skip to first unread message

Kent

unread,
May 24, 2001, 1:01:48 AM5/24/01
to
I want to convert an int into a string of char in C on the mac.

At my college, we learned the

itoa(int const, char *str[], base)

(int-to-alpha)


which is a DOS function. Whats the equivalent on the mac?

Kent

Arthur H. Gold

unread,
May 24, 2001, 1:21:20 AM5/24/01
to

Right. There is no function `itoa()' in standard C. Use `sprintf()'
instead (which _is_ a standard function).

Please read the FAQ for this newsgroup at:
http://www.eskimo.com/~scs/C-faq/top.html

HTH,
--ag

--
Artie Gold, Austin, TX (finger the cs.utexas.edu account for more info)
mailto:ag...@bga.com or mailto:ag...@cs.utexas.edu
--
I am looking for work. Contact me.

Mathew Hendry

unread,
May 24, 2001, 2:20:29 AM5/24/01
to
On Thu, 24 May 2001 01:01:48 -0400, tyco...@yahoo.com (Kent) wrote:

>I want to convert an int into a string of char in C on the mac.
>
>At my college, we learned the
>
>itoa(int const, char *str[], base)
>

>which is a DOS function.

Actually it's a lot more common than that. But it's not standard.

>Whats the equivalent on the mac?

There's no standard function that provides the usual functionality of itoa.
sprintf will do bases 8, 10, and 16, but not the others. You could use something
like

char *
my_uitoa(unsigned n, char *s, int radix) {
static const char tab[] = "0123456789abcdef";
char *p = s, *q = s;

/* generate digits in reverse order */
do {
*p++ = tab[n % radix];
n /= radix;
} while (n != 0);

*p-- = '\0';

/* reverse digits */
while (q < p) {
int temp = *p;
*p-- = *q;
*q++ = temp;
}

return s;
}

char *
my_itoa(int n, char *s, int radix) {
if (n >= 0) {
return my_uitoa(n, s, radix);
} else {
*s = '-';
return my_uitoa(-(unsigned)n, s + 1, radix) - 1;
}
}

You may want to add some error checking for null s, invalid radix etc.

-- Mat.

-hs-

unread,
May 24, 2001, 3:50:01 AM5/24/01
to
Mathew Hendry a écrit dans le message ...

>There's no standard function that provides the usual functionality of
itoa.
>sprintf will do bases 8, 10, and 16, but not the others. You could
use something
>like
>
> char *
> my_uitoa(unsigned n, char *s, int radix) {

Huh! What's wrong with sprintf() ?

--
-hs- "spaces, not tabs" email: emdel at noos.fr
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://secure.dinkumware.com/htm_cl/
FAQ de FCLC : http://www.isty-info.uvsq.fr/~rumeau/fclc


Mathew Hendry

unread,
May 24, 2001, 4:08:55 AM5/24/01
to
On Thu, 24 May 2001 09:50:01 +0200, "-hs-" <email....@server.invalid> wrote:

>Mathew Hendry a écrit dans le message ...
>>There's no standard function that provides the usual functionality of
>itoa.
>>sprintf will do bases 8, 10, and 16, but not the others. You could
>use something
>>like
>>
>> char *
>> my_uitoa(unsigned n, char *s, int radix) {
>
>Huh! What's wrong with sprintf() ?

Like I said, it doesn't handle all the bases supported by a typical
implementation of itoa.

-- Mat.

-hs-

unread,
May 24, 2001, 4:28:57 AM5/24/01
to
Mathew Hendry a écrit dans le message ...
>>>sprintf will do bases 8, 10, and 16, but not the others. <...>

>>Huh! What's wrong with sprintf() ?
>
>Like I said, it doesn't handle all the bases supported by a typical
>implementation of itoa.

Ah, apologies. I didn't read your reply carefully enough.

Mathew Hendry

unread,
May 24, 2001, 4:53:02 AM5/24/01
to
On Thu, 24 May 2001 07:20:29 +0100, Mathew Hendry <mathew...@my-deja.com>
wrote:

>...


> char *
> my_uitoa(unsigned n, char *s, int radix) {

>...

BTW, before I posted this, I was looking around for a particularly elegant
solution I'd seen that uses a lookup table to do the whole job in one pass
(without having to reverse the string at the end or estimate the logarithm of
n). Anyone seen this? glibc seems to do something along these lines, but it's so
hairy I couldn't fully decipher it. :)

Anyway, in my travels I happened upon the implementation used in Visual C++'s
standard library. It uses roughly the same approach as mine, but here's the
final string reversal

/* [MH: firstdig points initially to the first character in the string,
p to the last (i.e. p[1] == '\0') */

do {
temp = *p;
*p = *firstdig;
*firstdig = temp; /* swap *p and *firstdig */
--p;
++firstdig; /* advance to next two digits */
} while (firstdig < p); /* repeat until halfway */

So if the result string is only one character long, it

a) unnecesarily swaps a digit with itself
b) decrements p to before the beginning of the string - possible undefined
behaviour!

Of course this is within their own standard library, so they can do what they
like, but still... :)

-- Mat.

CBFalconer

unread,
May 24, 2001, 5:20:33 AM5/24/01
to
Kent wrote:
>
> I want to convert an int into a string of char in C on the mac.
> At my college, we learned the
>
> itoa(int const, char *str[], base)
>
> which is a DOS function. Whats the equivalent on the mac?

No direct equivalent in std C. You can use the following
routines:

#include <stdio.h>
#include <string.h>

/* ============================================ */
/* Mask and convert digit to hex representation */
/* Output range is 0..9 and a..f only */
int hexify(unsigned int value)
{
int result;

result = (value & 0x0f) + '0';
if (result > '9')
result = result + ('a' - '0' - 10);
return result;
} /* hexify */

/* ========================================= */
/* convert number to string in various bases */
/* 2 <= base <= 16, controlled by hexify() */
/* Output string has ls digit first. */
void basedisplay(unsigned long number, unsigned int base,
char * string, size_t maxlgh)
{
/* assert (string[maxlgh]) is valid storage */
if (!maxlgh) {
*string = '\0';
return;
}
else {
*string = hexify(number % base);
if (!number) *string = '\0';
else {
basedisplay(number / base, base, &string[1], maxlgh - 1);
}
}
} /* basedisplay */

/* ======================= */
/* reverse string in place */
void revstring(char * string)
{
char * last, temp;

last = string + strlen(string); /* points to '\0' */
while (last-- > string) {
temp = *string; *string++ = *last; *last = temp;
}
} /* revstring */

/* =========== */
/* exercise it */
int main(void)
{
#define LGH 40
#define VALUE 1234567890

char string[LGH];
unsigned int base;

printf("\n");
for (base = 2; base <= 16; base++) {
basedisplay(VALUE, base, string, LGH - 1);
revstring(string);
printf("%2d %s\n", base, string);
}
return 0;
} /* main */

--
Chuck F (cbfal...@my-deja.com) (cbfal...@XXXXworldnet.att.net)
http://www.qwikpages.com/backstreets/cbfalconer :=(down for now)
(Remove "NOSPAM." from reply address. my-deja works unmodified)
mailto:u...@ftc.gov (for spambots to harvest)


Chris Torek

unread,
May 24, 2001, 5:29:32 AM5/24/01
to
[regarding producing the textual base-b representation of a value n]

In article <3qhpgtg364rm1aoks...@4ax.com>


Mathew Hendry <mathew...@my-deja.com> writes:
>BTW, before I posted this, I was looking around for a particularly
>elegant solution I'd seen that uses a lookup table to do the whole
>job in one pass (without having to reverse the string at the end or
>estimate the logarithm of n). Anyone seen this?

This is not really possible -- you have to know how many digits you
will need in advance, and that requires something that amounts to
computing log-base-b n. What *is* possible, and indeed quite easy,
is to *produce* the radix-b text representation "in reverse":

/* note: n should be unsigned, or at least nonnegative */
i = sizeof buf - 1;
buf[i] = '\0';
do {
buf[--i] = digits[n % b];
} while ((n /= b) != 0);
/* now buf[i .. sizeof buf - 1] hold the expanded number */

The maximum buffer size required is log_b(max{n}) + 1 (to account
for the '\0' terminator).

If single-digit numbers are common (they are) and division is
slow (it is), there is incentive to avoid at least some of the
divisions by expanding the loop a bit, e.g.:

while (n >= b) {
buf[--i] = digits[n % b];
n /= b;
}
buf[--i] = digits[n];

If particular bases are common (such as 8, 10, and 16), there is
also incentive to optimize for those bases. The / and % operations
are particularly easy for powers of 2 (such as 8 and 10), and
division by a constant is often faster than division by a variable,
so a generalized "itoa"-like function could actually be *slower*
than simply using a member of the printf() family.
--
In-Real-Life: Chris Torek, Wind River Systems
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

MWRon

unread,
May 24, 2001, 7:25:28 PM5/24/01
to
In article
<tycoon888-240...@ip229.montreal117.dialup.canada.psi.net>,
tyco...@yahoo.com (Kent) wrote:

>I want to convert an int into a string of char in C on the mac.
>
>At my college, we learned the
>
>
>
>itoa(int const, char *str[], base)

If you have CodeWarrior (which most people have for Mac Development)
Look in extras.c in the MSL C sources and you will find it there.

Ron

--
Get CW 7 Early Access CD
International : write to int...@metrowerks.com
Subject: Early Access CD please put your Country in the body
US and Canada please use: http://survey.metrowerks.com/wwdc/

New CW Newsgroups: codewarrior.java, codewarrior.java.embedded

Metrowerks - Ron Liechty - MW...@metrowerks.com

Lew Pitcher

unread,
May 27, 2001, 1:45:01 AM5/27/01
to
Mathew Hendry wrote:
>
> On Thu, 24 May 2001 01:01:48 -0400, tyco...@yahoo.com (Kent) wrote:
>
> >I want to convert an int into a string of char in C on the mac.
> >
> >At my college, we learned the
> >
> >itoa(int const, char *str[], base)
> >
> >which is a DOS function.
>
> Actually it's a lot more common than that. But it's not standard.
>
> >Whats the equivalent on the mac?
>
> There's no standard function that provides the usual functionality of itoa.
> sprintf will do bases 8, 10, and 16, but not the others. You could use something
> like
[20+ lines of code snipped]

> You may want to add some error checking for null s, invalid radix etc

Of course, there's always my favourite variant....

static char *_itoa(unsigned i, char *a, unsigned r) /* private fn */
{
if (i/r > 0) a = _itoa(i/r,a,r);
*a = "0123456789ABCDEF"[i%r];
return a+1;
}

char *itoa(int i, char *a, int r) /* public fn */
{
if ((r < 2) || (r > 16)) r = 10;
if (i < 0)
{
*a = '-';
*_itoa(-i,a+1,r) = 0;
}
else *_itoa(i,a,r) = 0;
return a;
}


Advantages: shorter (by a bit), no byteswap logic
Disadvantages: recursive code may be memory wasteful


--
Lew Pitcher

Master Codewright and JOAT-in-training
Registered Linux User #112576

Dave Vandervies

unread,
May 27, 2001, 2:05:05 PM5/27/01
to
In article <3B0FA8A7...@yesic.com>,
Lew Pitcher <lpit...@yesic.com> wrote:

>Of course, there's always my favourite variant....
>
>static char *_itoa(unsigned i, char *a, unsigned r) /* private fn */

^^
Is _itoa available to the programmer at file scope? (I suspect it is
without external linkage, but I'm not sure.)

>{
> if (i/r > 0) a = _itoa(i/r,a,r);
> *a = "0123456789ABCDEF"[i%r];
> return a+1;
>}
>
>char *itoa(int i, char *a, int r) /* public fn */
>{
> if ((r < 2) || (r > 16)) r = 10;
> if (i < 0)
> {
> *a = '-';
> *_itoa(-i,a+1,r) = 0;
> }
> else *_itoa(i,a,r) = 0;
> return a;
>}
>
>
>Advantages: shorter (by a bit), no byteswap logic
>Disadvantages: recursive code may be memory wasteful

In this case, wouldn't the memory use be bounded by the logarithm of
INT_MAX, which tends to be rather Small? I'd be surprised if this
particular recursion would cause memory problems under ordinary use.


dave

--
Dave Vandervies dj3v...@student.math.uwaterloo.ca
I note with glee, however, that he has yet to be able to *provide* a link to
the official c.l.c. charter he claims to have found. I suspect he's typing
one up now to be posted somewhere. --Mark A. Odell in comp.lang.c

Ben Pfaff

unread,
May 27, 2001, 2:33:41 PM5/27/01
to
dj3v...@student.math.uwaterloo.ca (Dave Vandervies) writes:

> In article <3B0FA8A7...@yesic.com>,
> Lew Pitcher <lpit...@yesic.com> wrote:
>
> >Of course, there's always my favourite variant....
> >
> >static char *_itoa(unsigned i, char *a, unsigned r) /* private fn */
> ^^
> Is _itoa available to the programmer at file scope? (I suspect it is
> without external linkage, but I'm not sure.)

No, it's not available. C90 7.1.3:

- All identifiers that begin with an underscore are
always reserved for use as identifiers with file scope
in both the ordinary identifier and tag name space.

Above, _itoa is an identifier with file scope in the ordinary
identifier namespace.
--
"In My Egotistical Opinion, most people's C programs should be indented six
feet downward and covered with dirt." -- Blair P. Houghton

Lew Pitcher

unread,
Jun 1, 2001, 1:44:32 AM6/1/01
to
Ben Pfaff wrote:
>
> dj3v...@student.math.uwaterloo.ca (Dave Vandervies) writes:
>
> > In article <3B0FA8A7...@yesic.com>,
> > Lew Pitcher <lpit...@yesic.com> wrote:
> >
> > >Of course, there's always my favourite variant....
> > >
> > >static char *_itoa(unsigned i, char *a, unsigned r) /* private fn */
> > ^^
> > Is _itoa available to the programmer at file scope? (I suspect it is
> > without external linkage, but I'm not sure.)
>
> No, it's not available.

OK. You seem to be saying that I shouldn't have called the function
_itoa().
(it's not available to the programmer at file scope)

I can live with that, and will correct my version.

> C90 7.1.3:
>
> - All identifiers that begin with an underscore are
> always reserved for use as identifiers with file scope
> in both the ordinary identifier and tag name space.
>
> Above, _itoa is an identifier with file scope in the ordinary
> identifier namespace.

Hmmm... But, your quote of C90 7.1.3 says that such identifiers
"are always reserved _for use_ as identifiers with file scope in both
the ordinary identifier and tag name space." Doesn't "reserved for use
as identifiers" mean that I can use such as an identifier? Wouldn't
"reserved _from_ use" indicate that I shouldn't use such as an
identifier? IF so, then, your original statement that (paraphrased) "the
identifier _itoa() is not available to the programmer at file scope"
seems to be in conflict with your quote from the standard.

I don't question your expertise in this situation, Ben. Rather, I
question my comprehension of the concerns and restrictions you've
highlighted. I'll defer to you if you'll answer yes or no to this
question: does the standard permit me to write a function called
_itoa(), to be used in file scope?

Richard Heathfield

unread,
Jun 1, 2001, 2:30:40 AM6/1/01
to
Lew Pitcher wrote:
>
> Hmmm... But, your quote of C90 7.1.3 says that such identifiers
> "are always reserved _for use_ as identifiers with file scope in both
> the ordinary identifier and tag name space." Doesn't "reserved for use
> as identifiers" mean that I can use such as an identifier?

No, it means that you can't.

> Wouldn't
> "reserved _from_ use" indicate that I shouldn't use such as an
> identifier?

Yes. Either way, the identifier is reserved. :-)

> IF so, then, your original statement that (paraphrased) "the
> identifier _itoa() is not available to the programmer at file scope"
> seems to be in conflict with your quote from the standard.

Nope. Ben's right, you're wrong, let's move on. :-)

> I don't question your expertise in this situation, Ben. Rather, I
> question my comprehension of the concerns and restrictions you've
> highlighted. I'll defer to you if you'll answer yes or no to this
> question: does the standard permit me to write a function called
> _itoa(), to be used in file scope?

No.

Unless you're writing an implementation, of course.

--
Richard Heathfield : bin...@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

Mathew Hendry

unread,
Jun 1, 2001, 5:09:35 AM6/1/01
to
Lew Pitcher <lpit...@yesic.com> wrote:

: static char *_itoa(unsigned i, char *a, unsigned r) /* private fn */


: {
: if (i/r > 0) a = _itoa(i/r,a,r);
: *a = "0123456789ABCDEF"[i%r];
: return a+1;
: }
:
: char *itoa(int i, char *a, int r) /* public fn */
: {
: if ((r < 2) || (r > 16)) r = 10;
: if (i < 0)
: {
: *a = '-';
: *_itoa(-i,a+1,r) = 0;

Rather

*_itoa(-(unsigned)i,a+1,r) = 0;

to avoid undefined behaviour for i < -INT_MAX.

: }
: else *_itoa(i,a,r) = 0;
: return a;
: }

-- Mat.

Michael Rubenstein

unread,
Jun 1, 2001, 7:55:05 AM6/1/01
to
On Fri, 01 Jun 2001 05:44:32 GMT, Lew Pitcher
<lpit...@yesic.com> wrote:

>Hmmm... But, your quote of C90 7.1.3 says that such identifiers
>"are always reserved _for use_ as identifiers with file scope in both
>the ordinary identifier and tag name space." Doesn't "reserved for use
>as identifiers" mean that I can use such as an identifier? Wouldn't
>"reserved _from_ use" indicate that I shouldn't use such as an
>identifier? IF so, then, your original statement that (paraphrased) "the
>identifier _itoa() is not available to the programmer at file scope"
>seems to be in conflict with your quote from the standard.

No. Later 7.1.3 says

If the program declares or defines an identifier with the
same name as an identifier reservedin that context (other
than as allowed by 7.1.7), the behavior is undefined.
--
Michael M Rubenstein

Mark McIntyre

unread,
Jun 1, 2001, 5:16:03 PM6/1/01
to
On Fri, 01 Jun 2001 05:44:32 GMT, Lew Pitcher <lpit...@yesic.com>
wrote:

>Ben Pfaff wrote:
>>
>> C90 7.1.3:
>>
>> - All identifiers that begin with an underscore are
>> always reserved for use as identifiers with file scope
>> in both the ordinary identifier and tag name space.
>>
>> Above, _itoa is an identifier with file scope in the ordinary
>> identifier namespace.
>
>Hmmm... But, your quote of C90 7.1.3 says that such identifiers
>"are always reserved _for use_ as identifiers with file scope in both
>the ordinary identifier and tag name space." Doesn't "reserved for use
>as identifiers" mean that I can use such as an identifier?

the word you need to focus on is "reserved" that means "retained" in
this context, ie retained for the implementation to use.

>Wouldn't
>"reserved _from_ use" indicate that I shouldn't use such as an

"Reserved from" is not english, so no, that would not make any sense.


--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>

Lew Pitcher

unread,
Jun 5, 2001, 1:43:57 AM6/5/01
to
OK, taking all the expert advice given so far (and adding a couple of
compatability features myself), I present my revised itoa() code. I've
made it my goal to, at some point, present the canonical recursive
itoa(), and to learn a bit more about the C language in doing so.

Here it is...


/*
** The following two functions together make up an itoa()
** implementation. Function i2a() is a 'private' function
** called by the public itoa() function.
**
** itoa() takes three arguments:
** 1) the integer to be converted,
** 2) a pointer to a character conversion buffer,
** 3) the radix for the conversion
** which can range between 2 and 36 inclusive
** range errors on the radix default it to base10
*/

static char *i2a(unsigned i, char *a, unsigned r)
{
if (i/r > 0) a = i2a(i/r,a,r);
*a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
return a+1;
}

char *itoa(int i, char *a, int r)

{
if ((r < 2) || (r > 36)) r = 10;


if (i < 0)
{
*a = '-';

*i2a(-(unsigned)i,a+1,r) = 0;
}
else *i2a(i,a,r) = 0;
return a;
}


Comments, anyone??

CBFalconer

unread,
Jun 5, 2001, 8:12:02 AM6/5/01
to

Nice. It is unsafe in that the maximum length of the output
string is not constricted.

I suggest you make the conversion char string a local (or even
global) static array. Otherwise it may (depending on compiler) be
recreated on each recursion. I would also use lower case letters,
but that is largely a matter of taste. UC does avoid l vs 1
confusion, but adds 0 vs O confusion.

Lew Pitcher

unread,
Jun 5, 2001, 8:30:12 AM6/5/01
to
On Tue, 05 Jun 2001 12:12:02 GMT, CBFalconer <cbfal...@my-deja.com>
wrote:
... wearing my "at work" hat now...

Unfortunately, in all the variations of the 'common' implementations
of itoa() that I've looked at (a small sample, to be sure), there's no
requirement (or even option) to validate the length of the output
buffer. Anyway, similar functions (sprintf() for instance) don't edit
the length of their buffer; I feel safe in leaving the bufferlength
unedited here as well.

Originally, I choose to make my implementation compatable with (one
of) the defacto standard implementations of itoa(), and I agree that
the model function has flaws. P'haps thats one of the reasons that the
standards committee neglected to designate itoa() as a standard
library function (despite it's widespread use). I guess another reason
might have been that there are at least three variations of itoa(),
based on parameterlist alone. I've seen

char *itoa(int i),
char *itoa(int i, char *a), and


char *itoa(int i, char *a, int r)

>I suggest you make the conversion char string a local (or even


>global) static array. Otherwise it may (depending on compiler) be
>recreated on each recursion. I would also use lower case letters,
>but that is largely a matter of taste. UC does avoid l vs 1
>confusion, but adds 0 vs O confusion.

Good suggestions. I may craft these changes with conditional
compilation, to allow the user some choice over which parameterlist
model and radix expansion the functions will use.

Lew Pitcher, Information Technology Consultant, Toronto Dominion Bank Financial Group
(Lew_P...@td.com)

(Opinions expressed are my own, not my employer's.)

CBFalconer

unread,
Jun 5, 2001, 1:18:14 PM6/5/01
to

Here is my current version for the same basic function. It
doesn't attempt to handle -ve values, but leaves that up to a
suitable wrapper function. hexify and revstring could well be
made static, but both may have other uses. The length control has
the advantage of allowing conversion of only the nth LSDs. I
don't believe it can ever get into undefined behavior if you don't
lie to it about the string length available, although you may not
like the results with invalid bases.

#include <stdio.h>
#include <string.h>

/* ======================= */


/* reverse string in place */
void revstring(char *string)
{

char *last, temp;

last = string + strlen(string); /* points to '\0' */
while (last-- > string) {
temp = *string; *string++ = *last; *last = temp;
}
} /* revstring */

/* ============================================ */


/* Mask and convert digit to hex representation */
/* Output range is 0..9 and a..f only */
int hexify(unsigned int value)
{
int result;

result = (value & 0x0f) + '0';
if (result > '9')
result = result + ('a' - '0' - 10);
return result;
} /* hexify */

/* ========================================= */
/* convert number to string in various bases */
/* 2 <= base <= 16, controlled by hexify() */

/* Returns actual output string length */
size_t basedisplay(unsigned long number, unsigned int base,
char *string, size_t maxlgh)
{
char *s;

/* assert (string[maxlgh]) is valid storage */

s = string;
if (maxlgh && base)
do {
*s = hexify(number % base);
s += 1;
} while (--maxlgh && (number = number / base) );
*s = '\0';
revstring(string);
return (s - string);
} /* basedisplay */

/* =========== */
/* exercise it */
int main(void)
{
#define LGH 40
#define VALUE 1234567890

char string[LGH];
unsigned int base;

int sz;

printf("base value\n");


for (base = 2; base <= 16; base++) {
basedisplay(VALUE, base, string, LGH - 1);

printf("%2d %s\n", base, string);
}

basedisplay(0, 10, string, 3);
printf("\nzero %s\n", string);

basedisplay(VALUE, 10, string, 3);
printf("3 lsdigits only, base 10 %s\n", string);

printf("\nBad calls:\n");

sz = (int)basedisplay(VALUE, 10, string, 0);
printf("0 length field \"%s\" sz = %d\n", string, sz);

sz = (int)basedisplay(VALUE, 1, string, 20);
printf("base 1, lgh 20 \"%s\" sz = %d\n", string, sz);

sz = (int)basedisplay(VALUE, 0, string, 20);
printf("base 0, lgh 20 \"%s\" sz = %d\n", string, sz);

return 0;
} /* main */

--

Chris Torek

unread,
Jun 5, 2001, 10:52:52 PM6/5/01
to
>Lew Pitcher wrote:
[all but the "interesting" line snipped]
>> *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];

In article <3B1CC246...@my-deja.com>
CBFalconer <cbfal...@worldnet.att.net> writes, in part:


>I suggest you make the conversion char string a local (or even
>global) static array. Otherwise it may (depending on compiler) be
>recreated on each recursion.

There is nothing to stop a compiler from doing something stupid
like this, but I would rate the likelyhood as no greater than the
compiler calling free(malloc(rand() % 100 + 1)) after every line. :-)

With one exception, a string literal is just an array. The type
of that array is (plain) char and the size is determined by the
number of characters inside the literal. The duration is static,
meaning the individual `char' elements have to stick around as long
as the program is executing. (The `char's themselves may be in
read-only storage, which means `const char [N]' would be a better
type than `char [N]', but there are historical problems with this.)

This is why you can do this:

char *hello(void) { return "hello"; }

but not this:

char *hello(void) { char buf[6] = "hello"; return buf; /*WRONG*/ }

The `value' of the array buf is of course the address of its first
element -- but the array itself evaporates away when hello() returns,
so that address is no longer useful. The string literal, by
contrast, creates an array of the same type as buf, but static
duration (and possibly read-only even though not const-qualified).
The `value' of that array is again the address of its first element,
but the array sticks around when hello() returns.

Given all of this, a compiler would have to work hard to figure
out that some string literal is not used after a function returns,
and copy its data into a local array on each entry to that function.
That data would have to appear somewhere else in the program -- so
this would mean having *two* copies while the function runs, plus
any overhead to set it up and tear it down. All of this `pessimization'
(opposite of optimization :-) ) can only be done in some special
cases. DeathStation C might do it, of course. :-)


--
In-Real-Life: Chris Torek, Wind River Systems
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167

http://claw.eng.bsdi.com/torek/ (not always up) I report spam to abuse@.

Reply all
Reply to author
Forward
0 new messages