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

max size for printf() format conversion?

P: n/a
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.

For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?

I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.

Thanks!
Matt

--
Matt Garman
email at: http://raw-sewage.net/index.php?file=email
Nov 14 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
Matt Garman <fa**@not-real.bogus> wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable. For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?
Two points: INT_MAX and INT_MIN could differ by more than one, so
to be on the save side you would have to take into account both if
you use the values of these limits. And for negative values you
would have to add one for the minus sign.
I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.


If my calculations aren't wrong you should be on the safe side with

#defined MAX_INT_LENGTH ( ( sizeof( int ) * CHAR_BIT + 1 ) / 3 + 1 )

(both for signed and unsigned ints, you can drop the final "+ 1" for
unsigned ints). This can be evaluated at compile time and should be
portable.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #2

P: n/a
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.

For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?

I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.


C89: The draft I use states that a single conversion can produce a
maximum of at least 509 characters.
C99 (standard): This limit goes up to 4095 characters.

If in doubt, use snprintf()/vsnprintf() if available (and malloc()).

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #3

P: n/a
Michael Mair <Mi**********@invalid.invalid> writes:
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.
For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?
I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.


C89: The draft I use states that a single conversion can produce a
maximum of at least 509 characters.
C99 (standard): This limit goes up to 4095 characters.


Right, but I don't think that's what he's looking for. A C99
implementation isn't required to limit printf output to 4095
characters, so you can't assume that

char buf[4096];
sprintf(buf, some_format, arg1, arg2, arg3);

won't overflow the buffer.

A function that would take a format string and return the maximum
possible length of the output it can generate would solve the problem.
If the format string contains "%s", of course, the result is limited
only by the possible length of a string. The limit for "%d" would
typically be 6 on a system with 16-bit int, 11 on a system with 32-bit
int. Floating-point formats are a bit more challenging. The limit
for "%p" is difficult or impossible to determine without intimate
knowledge of the system.

One trick mentioned here recently is to use fprintf() to print to
/dev/null (or an equivalent data sink) and check the result. This
gives you the length for a given set of arguments, not the maximum for
the format, but substituting INT_MIN for "%d" and so forth might give
you the answers you're looking for. One drawback is that this
performs output (at least virtually), so the performance might not be
acceptable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #4

P: n/a
On 31 May 2005 20:27:55 GMT, Je***********@physik.fu-berlin.de wrote
in comp.lang.c:
Matt Garman <fa**@not-real.bogus> wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.

For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?


Two points: INT_MAX and INT_MIN could differ by more than one, so


No, they can't. Look at paragraph 2 of 6.2.6.2 in the current
standard. INT_MIN must equal either -INT_MAX or (-INT_MAX - 1).

If you believe there is something in the standard that permits
anything else, please post the reference. I might be wrong, but I
don't think so.

--
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.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #5

P: n/a
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.

For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?


A negative value will be preceded by a minus sign,
so printing INT_MIN will produce one more character than
printing INT_MAX.

Floating-point conversions yield character counts that
are (I think) impossible to compute at compile time without
"outside help."

Depending on your application, you may also need to
worry about modifiers, e.g. "%99i", "%.18f". "%*.*g" might
be worst of all ...

C99 provides snprintf() and vsnprintf(), which won't
produce the answer as a compile-time value but will keep you
out of trouble if a particular conversion would take more
space than you allotted.

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 14 '05 #6

P: n/a
Keith Thompson wrote:
Michael Mair <Mi**********@invalid.invalid> writes:
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.
For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?
I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.
C89: The draft I use states that a single conversion can produce a
maximum of at least 509 characters.
C99 (standard): This limit goes up to 4095 characters.


Right, but I don't think that's what he's looking for. A C99
implementation isn't required to limit printf output to 4095
characters, so you can't assume that

char buf[4096];
sprintf(buf, some_format, arg1, arg2, arg3);

won't overflow the buffer.


Yep. Nonetheless, I think these environmental limits provide a
lower bound for or at least give an impression of sensible buffer
sizes.
As it is, I would use the respective buffer size in conjunction
with some strategy for error handling, i.e. if the static buffer
is not enough and a large enough dynamic buffer cannot be allocated,
one can try splitting the format string and at least get out
the minimum maximum number of characters per conversion...
A function that would take a format string and return the maximum
possible length of the output it can generate would solve the problem.
If the format string contains "%s", of course, the result is limited
only by the possible length of a string. The limit for "%d" would
typically be 6 on a system with 16-bit int, 11 on a system with 32-bit
int. Floating-point formats are a bit more challenging. The limit
for "%p" is difficult or impossible to determine without intimate
knowledge of the system.

One trick mentioned here recently is to use fprintf() to print to
/dev/null (or an equivalent data sink) and check the result. This
gives you the length for a given set of arguments, not the maximum for
the format, but substituting INT_MIN for "%d" and so forth might give
you the answers you're looking for. One drawback is that this
performs output (at least virtually), so the performance might not be
acceptable.


Well, on systems with such a "data sink" you also may have snprintf()
in the library, which IMO is a more obvious candidate for a solution.
Of course, one always should wrap a potentially not portable "character
count" solution appropriately...
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #7

P: n/a
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable. For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?
Well, a negative number might have one more character.

The %f conversion could generate very large strings on some machines,
such as some CRAY machines.
I'd like to create a structure that contains character
representations of numerical types (e.g., instead of storing 3421 as
an int, it would store the char array "3421"). I'd like to make
these fields a fixed-size static array, but obviously I don't want
to make them too small.


I would say that you should make them big enough for the values
you expect them to hold. You could write your own functions to
do arithmetic on such strings, which would remove the limitation
on their size.

-- glen

Nov 14 '05 #8

P: n/a
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
Matt Garman wrote:
Is there a clean, portable way to determine the maximum value of
converted numerical fields with printf()-like functions? Doing this
at compile-time would be preferable.

For example, %i should never convert to a string that is longer than
the number of digits in INT_MAX, right?


Well, a negative number might have one more character.

The %f conversion could generate very large strings on some machines,
such as some CRAY machines.


Actually, the largest floating-point ranges I've seen are on systems
with 128-bit IEEE floating-point, including ordinary x86 systems.
It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; such systems typically have
32, 64, and 128 bit floating-point types with 8, 11, and 15 bit
exponents.

Many of the more recent Cray systems use IEEE floating-point. On the
vector systems that use Cray floating point, they seem to support
64-bit and 128-bit formats, both with 13-bit exponents; the 128-bit
format therefore supports a narrower range (but slightly more
precision) than the 128-bit IEEE format.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #9

P: n/a
Keith Thompson wrote:

Actually, the largest floating-point ranges I've seen are on systems
with 128-bit IEEE floating-point, including ordinary x86 systems.
It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; [...]


printf ("%32767f", 0.0);

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 14 '05 #10

P: n/a
Keith Thompson <ks***@mib.org> writes:
Actually, the largest floating-point ranges I've seen are on systems
with 128-bit IEEE floating-point, including ordinary x86 systems.


Ordinary x86 systems do not have 128-bit IEEE floating-point,
unless by that you mean 80-bit IEEE floating-point plus 48
padding bits.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 14 '05 #11

P: n/a
Eric Sosman <es*****@acm-dot-org.invalid> writes:
Keith Thompson wrote:
It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; [...]


printf ("%32767f", 0.0);


That's undefined behavior:

7.19.6.1 The fprintf function
[...]
Environmental limits
15 The number of characters that can be produced by any single conversion shall be at least
4095.

--
"I'm not here to convince idiots not to be stupid.
They won't listen anyway."
--Dann Corbit
Nov 14 '05 #12

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> writes:
Keith Thompson <ks***@mib.org> writes:
Actually, the largest floating-point ranges I've seen are on systems
with 128-bit IEEE floating-point, including ordinary x86 systems.


Ordinary x86 systems do not have 128-bit IEEE floating-point,
unless by that you mean 80-bit IEEE floating-point plus 48
padding bits.


Ok, quite possibly; I haven't looked into it in great detail.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #13

P: n/a
Ben Pfaff wrote:
Eric Sosman <es*****@acm-dot-org.invalid> writes:

Keith Thompson wrote:
It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; [...]


printf ("%32767f", 0.0);

That's undefined behavior:

7.19.6.1 The fprintf function
[...]
Environmental limits
15 The number of characters that can be produced by any single conversion shall be at least
4095.

It says 'at least', not 'at most'.

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #14

P: n/a
Joe Wright <jo********@comcast.net> writes:
Ben Pfaff wrote:
Eric Sosman <es*****@acm-dot-org.invalid> writes:
Keith Thompson wrote:

It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; [...]

printf ("%32767f", 0.0);

That's undefined behavior:
7.19.6.1 The fprintf function
[...]
Environmental limits
15 The number of characters that can be produced by any single conversion shall be at least
4095.

It says 'at least', not 'at most'.


You can't depend on support for any more than the minimum, and
thus the behavior is undefined in general.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x1f6},*p=
b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case
2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Nov 14 '05 #15

P: n/a
Jack Klein <ja*******@spamcop.net> wrote:
On 31 May 2005 20:27:55 GMT, Je***********@physik.fu-berlin.de wrote
in comp.lang.c:
Matt Garman <fa**@not-real.bogus> wrote:
> Is there a clean, portable way to determine the maximum value of
> converted numerical fields with printf()-like functions? Doing this
> at compile-time would be preferable.

> For example, %i should never convert to a string that is longer than
> the number of digits in INT_MAX, right?


Two points: INT_MAX and INT_MIN could differ by more than one, so

No, they can't. Look at paragraph 2 of 6.2.6.2 in the current
standard. INT_MIN must equal either -INT_MAX or (-INT_MAX - 1). If you believe there is something in the standard that permits
anything else, please post the reference. I might be wrong, but I
don't think so.


It looks as if the screws got tightened quite a bit in C99 relative
to C89 - while I don't doubt what you write for C99 I haven't been
able to find something in the C89 standard that would nail down the
values that tightly. But that's probably due to me not reading the
whole thing carefully enough.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #16

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> writes:
Joe Wright <jo********@comcast.net> writes:
Ben Pfaff wrote:
Eric Sosman <es*****@acm-dot-org.invalid> writes:

Keith Thompson wrote:

>It's basically the size of the exponent that determines how big a
>string the "%f" conversion can generate; [...]

printf ("%32767f", 0.0);
That's undefined behavior:
7.19.6.1 The fprintf function
[...]
Environmental limits
15 The number of characters that can be produced by any single
conversion shall be at least 4095.

It says 'at least', not 'at most'.


You can't depend on support for any more than the minimum, and
thus the behavior is undefined in general.


I suppose it's undefined behavior in the sense that the standard
doesn't guarantee that it will work. On the other hand, an
implementation could choose to guarantee a larger number of
characters, or it could state that there are no fixed limits, only
those imposed by resource constraints. (I think the latter is fairly
common.)

If I want to write a function that will take a printf-style format
string and return the maximum length of the resulting string (or an
error indicator if it contains something unbounded like "%s"), it
would be foolish to assume that the standard's limits will never be
exceeded.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #17

P: n/a
Keith Thompson wrote:
.... snip ...
If I want to write a function that will take a printf-style format
string and return the maximum length of the resulting string (or an
error indicator if it contains something unbounded like "%s"), it
would be foolish to assume that the standard's limits will never be
exceeded.


IMNSHO no output function should show invalid significant digits
after a decimal point. It should round the last digit as
appropriate, and output blanks from there on. For digits before a
decimal point zeroes can be used, with the same fundamental rule.

--
"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 #18

P: n/a
CBFalconer <cb********@yahoo.com> writes:
Keith Thompson wrote:

... snip ...

If I want to write a function that will take a printf-style format
string and return the maximum length of the resulting string (or an
error indicator if it contains something unbounded like "%s"), it
would be foolish to assume that the standard's limits will never be
exceeded.


IMNSHO no output function should show invalid significant digits
after a decimal point. It should round the last digit as
appropriate, and output blanks from there on. For digits before a
decimal point zeroes can be used, with the same fundamental rule.


Was that intended to be relevant to the paragraph you quoted?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #19

P: n/a
Keith Thompson wrote:
CBFalconer <cb********@yahoo.com> writes:
Keith Thompson wrote:

... snip ...

If I want to write a function that will take a printf-style format
string and return the maximum length of the resulting string (or an
error indicator if it contains something unbounded like "%s"), it
would be foolish to assume that the standard's limits will never be
exceeded.


IMNSHO no output function should show invalid significant digits
after a decimal point. It should round the last digit as
appropriate, and output blanks from there on. For digits before a
decimal point zeroes can be used, with the same fundamental rule.


Was that intended to be relevant to the paragraph you quoted?


Yes - it has to do with the boundedness of a displayed value.

--
"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 #20

P: n/a
Keith Thompson <ks***@mib.org> wrote:
Ben Pfaff <bl*@cs.stanford.edu> writes:
Joe Wright <jo********@comcast.net> writes:
Ben Pfaff wrote:
Eric Sosman <es*****@acm-dot-org.invalid> writes:

> printf ("%32767f", 0.0);
That's undefined behavior: 15 The number of characters that can be produced by any single
conversion shall be at least 4095.

It says 'at least', not 'at most'.


You can't depend on support for any more than the minimum, and
thus the behavior is undefined in general.


I suppose it's undefined behavior in the sense that the standard
doesn't guarantee that it will work. On the other hand, an
implementation could choose to guarantee a larger number of
characters, or it could state that there are no fixed limits, only
those imposed by resource constraints.


So they could, but that doesn't make it any less undefined by the
Standard. An implementation can choose to define, for itself only, _any_
case of undefined behaviour. If an implementation wants to define that
passing a null pointer to strlen() returns 0, that's fine. Doesn't make
passing null pointers to strlen() any more defined, though - except for
that implementation. The same is true in this case.

Richard
Nov 14 '05 #21

P: n/a
Keith Thompson wrote:
I suppose it's undefined behavior in the sense that the standard
doesn't guarantee that it will work.


That's as undefined as code can get.

N869
3. Terms and definitions
3.18
[#1] undefined behavior
behavior, upon use of a nonportable or erroneous program
construct, of erroneous data, or of indeterminately valued
objects, for which this International Standard imposes no
requirements

--
pete
Nov 14 '05 #22

P: n/a
Keith Thompson wrote:
(snip)
Actually, the largest floating-point ranges I've seen are on systems
with 128-bit IEEE floating-point, including ordinary x86 systems.
It's basically the size of the exponent that determines how big a
string the "%f" conversion can generate; such systems typically have
32, 64, and 128 bit floating-point types with 8, 11, and 15 bit
exponents.
I don't know that many supply a printf conversion for the 80 bit
format, though.
Many of the more recent Cray systems use IEEE floating-point. On the
vector systems that use Cray floating point, they seem to support
64-bit and 128-bit formats, both with 13-bit exponents; the 128-bit
format therefore supports a narrower range (but slightly more
precision) than the 128-bit IEEE format.


The CRAY-1 has a 15 bit biased exponent, but it can only have
values between octal 20000 and 57777, or, so they say, approximately
1e-2500 to 1e+2500. One could, then, expect up to 2500 digits from
a %f format item.

-- glen

Nov 14 '05 #23

P: n/a
In article <8v********************@comcast.com> glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
Keith Thompson wrote:

....
Many of the more recent Cray systems use IEEE floating-point. On the
vector systems that use Cray floating point, they seem to support
64-bit and 128-bit formats, both with 13-bit exponents; the 128-bit
format therefore supports a narrower range (but slightly more
precision) than the 128-bit IEEE format.


The CRAY-1 has a 15 bit biased exponent, but it can only have
values between octal 20000 and 57777, or, so they say, approximately
1e-2500 to 1e+2500. One could, then, expect up to 2500 digits from
a %f format item.


The Cyber 205 had a 16 bits 2-s complement exponen, providing nearly
the whole range. 0x8000 (which should be the minimum exponent) indicated
that the number was 0.0. (An example of a machine where all 0 bits in
a floating point number did not give you 0.0. If I remember well, the
floating point format was similar to that used in some Milspec processor.)
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.