portably printing a size_t

T

Tim Rentsch

Francois Grieu said:
Peter Nilsson wrote : [snip]
if ((size_t) -1 <= UINT_MAX)

I have always wondered if these are equivalent. To reduce to a
simpler thing, how do we demonstrate the following holds?
(unsigned long)~(unsigned long)0 == (unsigned long)-1

The expression (size_t) -1 is guaranteed to be the maximum
value that a (size_t) can have, because of the rules for
how out-of-range values are converted to unsigned types.

[snip]
Of course, you could just roll your own %zu printer...

#include <stdio.h>
int fputz(size_t z, FILE *fp)
{
char b[(sizeof(z) * CHAR_BIT + 5)/ 3];
char t, *p, *q;

q = b;
do
{
*q++ = '0' + (z % 10u);

This is portable to every machine I know, but in this group,
*q++ = "0123456789"[z % 10u];
might be even less objectionable.

The expression '0' + z%10 is guaranteed to work (assuming
z is non-negative), because the standard says decimal digits
have increasing-by-one values after '0'.

} while (z /= 10u);
*q = 0;

for (p = b; p < --q; p++)
{
t = *p;
*p = *q;
*q = t;
}

return fputs(b, fp);
}

Francois Grieu


Again the admittedly pedantic (now fixed):
[long function snipped]

Why not just take Peter's suggestion, modified to always use
printf() rather than taking a (FILE *)? His function can be
shortened a bit, but even as is it has a pretty small footprint,
and doesn't need any integer types other than size_t (and char,
which doesn't count).
 
F

Francois Grieu

Ben Bacarisse wrote :
Francois Grieu said:
pete said:
((unsigned long)-1) equals ULONG_MAX.

N869
6.2.5 Types

[#9]

A computation involving unsigned operands
can never overflow, because a result that cannot be
represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the
largest value that can be represented by the resulting type.
This shows that
((unsigned long)0-(unsigned long)1) equals ULONG_MAX
and even possibly that
(-(unsigned long)1) equals ULONG_MAX
although many compilers at least emit a warning when unary minus
is applied to an unsigned type.

But I fail to see how one goes from here to
((unsigned long)-1) equals ULONG_MAX.

pete quoted the wrong paragraph. You want 6.3.1.3 paragraph 2 which
says pretty much the same but in the context of converting a signed
integer to unsigned.

Ah yes, thanks. And that also holds in C89; quoting 3.2.1.2 paragraph 2:
"When a signed integer is converted to an unsigned integer with
equal or greater size, if the value of the signed integer is
nonnegative, its value is unchanged. Otherwise: if the unsigned
integer has greater size, the signed integer is first promoted to the
signed integer corresponding to the unsigned integer; the value is
converted to unsigned by adding to it one greater than the largest
number that can be represented in the unsigned integer type."

Francois Grieu
 
F

Francois Grieu

Tim Rentsch wrote :
Francois Grieu said:
Peter Nilsson wrote :
*q++ = '0' + (z % 10u);
This is portable to every machine I know, but in this group,
*q++ = "0123456789"[z % 10u];
might be even less objectionable.

The expression '0' + z%10 is guaranteed to work (assuming
z is non-negative), because the standard says decimal digits
have increasing-by-one values after '0'.

Now I know that under both C89 and C99, "In both the source and
execution basic character sets, the value of each character after 0 in
the (..) list of decimal digits ( 0 1 2 3 4 5 6 7 8 9 ) shall be one
greater than the value of the previous."


Francois Grieu
 
P

Phil Carmody

Francois Grieu said:
I have always wondered if these are equivalent. To reduce to a
simpler thing, how do we demonstrate the following holds?
(unsigned long)~(unsigned long)0 == (unsigned long)-1

Both sides, when 1 is added to them, must equal 0. By injectivity
of addition of 1 in modulo aritmetic mod 2^${bits_in_ulong}, they
must therefore be equal themselves. I hope!

Unfortunately the conversion/promotion rules are a tad more
complicated in C than in some other languages, so perhaps there's
some scary corner case which can make it not hold. (Some were
played with a few months here, I think Keith prodded c.s.c with
some of the more 'curious' conclusions.)

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,434
Messages
2,571,689
Members
48,796
Latest member
Greg L.

Latest Threads

Top