F
Francois Grieu
How can we portably print (or convert to a string representation)
the value of a variable of type size_t?
Francois Grieu
the value of a variable of type size_t?
Francois Grieu
Francois Grieu said:How can we portably print (or convert to a string representation)
the value of a variable of type size_t?
> Also, C99 has %zu (where z tells printf() that the unsigned
> argument is a size_t.)
Francois said:Beej Jorgensen wrote :
The FAQ suggest: "Use a cast to convert the value to a known,
conservatively-sized type, then use the printf format matching
that type"
and shows (paraphrased)
printf("my_len = %lu", (unsigned long)my_len);
The above is portable in the sense that it compiles and runs without
causing undefined behavior; but not in the sense that it shows the
value of my_len<offtopic>; one platform where it fails is 64-bit
windows</offtopic>.
Can we portably choose a conservatively-sized type, and the
associated printf format?
I know environments with C99 extensions which do not support this
particular C99 extension.
Francois said:I know environments with C99 extensions which do not support this
particular C99 extension.
Rui Maciel said:Then those compilers fail to comply with the C99 standard.
You could replace this line with:
if(1)
or simply remove it altogether. ITYM: if((size_t)-1 <= UINT_MAX).
<snip>
---------------/Richard Heathfield wrote :
Is it meant to be humorous? Or maybe the characters '~' '-' and/or
'!' are mysteriously swapped by whatever we use to communicate?
If not, allow me to remark that "size_t" can be "unsigned long"
even if "unsigned int" is limited to 65535. In this case
(size_t)~(size_t)0 will equal ULONG_MAX, which
is at least 4294967295, thus (size_t)~(size_t)0<=UINT_MAX will
evaluate to false.
I wrote :
---------------/
Wrong wording for the group, read: evaluate to 0
Francois Grieu
jacob navia said:Francois Grieu a écrit :I wrote : [...]---------------/If not, allow me to remark that "size_t" can be "unsigned long"
even if "unsigned int" is limited to 65535. In this case
(size_t)~(size_t)0 will equal ULONG_MAX, which
is at least 4294967295, thus (size_t)~(size_t)0<=UINT_MAX will
evaluate to false.
Wrong wording for the group, read: evaluate to 0
Francois Grieu
Why?
Standard C defines "false" in stdbool.h. That some people here claim that
"it is not portable" etc because they want to stay in 1989 doesn't mean
that this *whole* group follows them.
Francois Grieu said:At the end of the day, I settle for the admittedly pedantic:
[...]I think it is portable to virtually all systems where printf
is available and supports "unsigned long".
The code struggles to avoid pointless use of recursion,
or of "unsigned long" when "unsigned int" would do.
Francois Grieu said:At the end of the day, I settle for the admittedly pedantic:
[code snipped]
[...]I think it is portable to virtually all systems where printf
is available and supports "unsigned long".
The code struggles to avoid pointless use of recursion,
or of "unsigned long" when "unsigned int" would do.
I don't see the point of avoiding unsigned long. If there are any
surviving compilers that don't support unsigned long (they'd have to
be pre-ANSI), it's likely they don't support <limits.h> either.
Keith Thompson said:Of course they do. Nevertheless, they exist, and some programmers
need to deal with them.
Francois Grieu said:---------------/
Wrong wording for the group, read: evaluate to 0![]()
Yes; the problem is, though, where do you stop? If you take all kinds of
semi-compatible implementations into account, sooner or later you're
going to run into one which supports some, but not all, parts of the C90
Standard, and the part which it doesn't support is the one where
unsigned long is the largest integer type. Or that size_t is an integer
at all.
Basically, we have to assume _something_. The most practical option,
ISTM, is to assume that we have two Standards, and any implementation
which does not choose either C90, or C99, or C90 with a set of
_coherent_ C99 extensions, is too much trouble to be worth taking into
account unless we specifically have to.
In this case, we assume that any implementation worth considering has
either %zu (C99), or a size_t smaller or equal to unsigned long (C90),
or both. Any implementation writer who has picked longer-than-long
size_t from C99, but _not_ %zu, is being incoherent, and thereby doing
his users sufficient disservice to ignore him.
Francois Grieu said:At the end of the day, I settle for the admittedly pedantic:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
/* output the decimal representation of a size_t on stdout */
show_size_t(size_t n)
{
if ((size_t)~(size_t)0<=UINT_MAX)
/* size_t fits an "unsigned int" */
printf("%u",(unsigned int)n);
else
if (ULONG_MAX>UINT_MAX)
/* "unsigned long" wider than "unsigned int" */
if ((size_t)~(size_t)0<=ULONG_MAX || n<=ULONG_MAX)
printf("%lu",(unsigned long)n);
else /* n does not fit an unsigned long */
{
show_size_t(n/1000000000ul);
printf("%09lu",(unsigned long)(n%1000000000ul));
}
else /* "unsigned int" equivalent to "unsigned long" */
if (n<=UINT_MAX)
printf("%u",(unsigned int)n);
else /* n does not fit an "unsigned int */
{
show_size_t(n/1000000000ul);
printf("%09u",(unsigned int)(n%1000000000ul));
}
}
I think it is portable to virtually all systems where printf
is available and supports "unsigned long". ...
I rejected several other options because some very real
environments (such as the current MinwGW) have support for the
type "unsigned long long" but not for the format specifiers
"%wu" or "%llu".
Oooops !You're using implicit int here!
if ((size_t) -1 <= UINT_MAX)
If you're going to include <limits.h>, why not simply do...
#include <limits.h>
#include <stdout.h>
void fputz(size_t z, FILE *fp)
{
#if SIZE_MAX > ULONG_MAX
fprintf(fp, "%zu", z);
#else
fprintf(fp, "%lu", (unsigned long) z);
#endif
}
You use unsigned long in the code above, so do actually mean
(doesn't) support %lu?
I rejected several other options because some very real
environments (such as the current MinwGW) have support for the
type "unsigned long long" but not for the format specifiers
"%wu" or "%llu".
Surely 2 unsigned longs worth is enough?! If you can find
a hosted system that supports 800+ petabyte objects or
files, but doesn't support %lu, then I'd say you have more
issues than just being able to print a size_t.![]()
True.
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);
} while (z /= 10u);
*q = 0;
for (p = b; p < --q; p++)
{
t = *p;
*p = *q;
*q = t;
}
return fputs(b, fp);
}
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.
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.
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.