What is the portable way to output a value of type size_t? On some
systems (e.g. 16 bit machines) size_t is typically typedefed as
unsigned long, on others it is unsigned int. How do I know which
conversion specifier in printf, i.e. %u or %lu should be used.
The same problem occurs with time_t, ptrdiff_t, ...
urs
What about
size_t val;
printf("%lu\n", (unsigned long)size_t);
hfs
[F'up,CC]
--
Hans Friedrich Steffani
Institut fuer Elektrische Maschinen und Antriebe, TU Chemnitz-Zwickau
mailto:hans.s...@e-technik.tu-chemnitz.de
http://www.tu-chemnitz.de/~hfst/
Since size_t is an unsigned integer type, cast it to unsigned long and use
%lu. Similarly, ptrdiff_t is a signed integer type so cast it to signed long
and use %ld.
For things like clock_t and time_t you are out of luck since these could be
floating-point or integer types. These are intended to be magic cookies for
internal use only and to accomodate the variety of prior art, not for I/O.
Rex
----------------------------------------------------------------------------
+1 703 860-0091 | Rex Jaeschke | C and C++ Seminars
FAX +1 703 860-3008 | 2051 Swans Neck Way | and Consulting
r...@aussie.com | Reston, Virginia 20191-4023, USA |
----------------------------------------------------------------------------
Chair of X3J11 (ANSI C) and participant in SC22/WG14 (ISO C). Columnist for
NT Developer and VC++ Professional.
----------------------------------------------------------------------------
>>What is the portable way to output a value of type size_t? ...
>What about
>size_t val;
>
>printf("%lu\n", (unsigned long)size_t);
There are two difficulties, it seems to me. Recall that
the cast rules for stdarg functions imply a certain type
of promotion, even if the user applies a specific cast first.
Thus, it seems to me, the explicit cast to (unsigned long)
is redundant. There may be other cases where it's not
redundant, though I can't think of any.
The real difficulty is how to know to write "%lu" in the format.
The only way to know this is to look in the .h file where
size_t is typedef'ed, and see what it is defined to be.
This is a major problem in the use of typedef's in C. They're
great for simplifying complex declarations and for writing
self-documenting code, but the "type hiding" that they
also are said to be good for breaks down when it comes to
IO.
For instance, suppose you have code that looks like this:
typedef float My_real_type;
...
My_real_type x;
scanf( "%f", &x );
...
Now, later, you want to change the typedef to read as
follows:
typedef double My_real_type;
You still have to go through all the code and correct your
scanf's to agree with the new typedef. This cannot be
made automatic in C, unfortunately.
-P.
--
********************* (Note new snail-mail address.) **********************
* Peter S. Shenkin, Chemistry, Columbia U., 3000 Broadway, Mail Code 3153,*
** NY, NY 10027; she...@columbia.edu; (212)854-5143; FAX: 678-9039 ***
MacroModel WWW page: http://www.cc.columbia.edu/cu/chemistry/mmod/mmod.html
It is not redundant in general, because in some compilers,
size_t is unsigned int, and unsigned long is longer than unsigned int.
This is true for most 16 bit compilers, size_t is 16 bits, long is 32 bits.
The above printf works in all ANSI compilers.
>The real difficulty is how to know to write "%lu" in the format.
>The only way to know this is to look in the .h file where
>size_t is typedef'ed, and see what it is defined to be.
No. You write %lu because you cast to unsigned long.
You cast to unsigned long because it is the shortest type
that is long enough in all compilers. You DON'T go looking
in the .h file, because that does NOT tell you what all
compilers do, it only tells you what one specific compiler does.
>This is a major problem in the use of typedef's in C. They're
>great for simplifying complex declarations and for writing
>self-documenting code, but the "type hiding" that they
>also are said to be good for breaks down when it comes to
>IO.
>
>For instance, suppose you have code that looks like this:
>
>typedef float My_real_type;
>...
> My_real_type x;
> scanf( "%f", &x );
> ...
Rule 1: Don't use scanf().
Rule 2: Don't use gets().
So the above should be changed to use fgets() and strtod().
strtod() returns double which should be casted(sp?) to My_real_type.
If you do this a lot, you might write get_my_real_type() which
would return a My_real_type and cut down on the number
of casts.
>Now, later, you want to change the typedef to read as
>follows:
>
>typedef double My_real_type;
>
>You still have to go through all the code and correct your
>scanf's to agree with the new typedef. This cannot be
>made automatic in C, unfortunately.
This is not a problem if you use fgets() and strtod() instead
of scanf() which should never be used in new code.
--
den...@netcom.com (Dennis Yelle)
"You must do the thing you think you cannot do." -- Eleanor Roosevelt
Well, you are on X3J11 and I am not, but I cannot believe that
there is a current compiler that would fail to give the
right result if a clock_t or a time_t was cast to a double and
printed with %f. Is there anything in the standard that says
that I am in trouble if I do this?
Obviously, I would probably divide the clock_t by
CLOCKS_PER_SEC before showing it to most people, but
I don't see why I am REQUIRED to do it.
>In article <50mnhh$g...@narses.hrz.tu-chemnitz.de>,
>Hans Steffani <hf...@hrz.tu-chemnitz.de> wrote:
>>thue...@ibr.cs.tu-bs.de (Urs Thuermann) writes:
>>>What is the portable way to output a value of type size_t? ...
>>What about
>>size_t val;
>>
>>printf("%lu\n", (unsigned long)size_t);
>The real difficulty is how to know to write "%lu" in the format.
>The only way to know this is to look in the .h file where
>size_t is typedef'ed, and see what it is defined to be.
No. (unsigned long)size_t has the type unsigned long and
unsigned longs have to print with %lu. If there is some
casting by propagation rules it will happen as to every
other argument of type unsigned long.
>You still have to go through all the code and correct your
>scanf's to agree with the new typedef. This cannot be
>made automatic in C, unfortunately.
This is correct, but the orignal problem was a printf().
h.f.s.
Consider the case of a machine with 64-bit ints and 64-bit IEEE doubles. You
lose significant digits when casting large integer values to double. So yes,
you can do the cast but you may only get an approximation of the original
value. Strictly speaking we shoul be using long double instead of double but
on many implementations that's a synonym for double (e.g., Alpha, which does
not support extended IEEE precision in h/w).
Rex
But where is the guarantee that size_t fits into (unsigned long)??
Suppose instead it requires (unsigned long long long) or some other
such idiocy??
Let the power of gcc 2.7.2 amaze you!
$ cat foo.c
#include <stdio.h>
extern int
main( void )
{
typedef double My_real_type;
My_real_type x;
scanf( "%f", &x );
return 0;
}
$ gcc -Wformat -c foo.c
foo.c: In function `main':
foo.c:8: warning: float format, My_real_type arg (arg 2)
$
Cheers
Geoff
--
s...@quango.demon.co.uk
http://www.quango.demon.co.uk
>But where is the guarantee that size_t fits into (unsigned long)??
Right into the standard:
size_t
which is the unsigned integral type of the result of the sizeof
operator; ^^^^^^^^^^^^^^^^^^^^^^
>Suppose instead it requires (unsigned long long long) or some other
>such idiocy??
unsigned long long long (or some other such idiocy) is not an unsigned
integral type. The only unsigned integral types in C are:
unsigned char
unsigned short
unsigned int
unsigned long
It is guaranteed that size_t is one of these types, because this list
is exhaustive.
Dan
--
Dan Pop
CERN, CN Division
Email: Dan...@cern.ch
Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland
In the Standard. size_t must be an unsigned integral type.
>Suppose instead it requires (unsigned long long long) or some other
>such idiocy??
There's no such type. size_t must be one of unsigned char, unsigned
short, unsigned int or unsigned long. unsigned long can represent all
values representable in any of these types, and it is the only type
with this property.
Nit-picky question: can size_t be char, if char is unsigned?
-zefram
>Nit-picky question: can size_t be char, if char is unsigned?
The following paragraph suggests that the answer is no:
The type char, the signed and unsigned integer types, and the
floating types are collectively called the basic types.
There are other paragraphs enforcing this conclusion in ANSI Classic
3.1.2.5. char is an integral type, but its neither signed nor unsigned :-)
No. The 4 types you mention are the only 4 unsigned integral types.
"char" is neither a signed nor an unsigned integral type.
--
Clive D.W. Feather | Associate Director | Director
Tel: +44 181 371 1138 | Demon Internet Ltd. | CityScape Internet Services Ltd.
Fax: +44 181 371 1150 | <cl...@demon.net> | <cd...@cityscape.co.uk>
Written on my laptop - please reply to the Reply-To address <cl...@demon.net>
Well, you *still* have to go through all the code and
correct all your (printf, scanf, etc.) functions to agree
with the new typedef. Though it's nice to knew gcc can
tell you if you've blown it.
-P.
--
****** ********** In Memoriam, Bill Monroe, 1911 - 1996 ******************
: For instance, suppose you have code that looks like this:
: typedef float My_real_type;
: ...
: My_real_type x;
: scanf( "%f", &x );
: ...
: Now, later, you want to change the typedef to read as
: follows:
: typedef double My_real_type;
: You still have to go through all the code and correct your
: scanf's to agree with the new typedef. This cannot be
: made automatic in C, unfortunately.
If you route all your IO via an intermediate double value then you
have no problems and you code will be portable. [But it is more work,
especially for input.]
--
Stephen Baynes bay...@ukpsshp1.serigate.philips.nl
Philips Semiconductors Ltd
Southampton My views are my own.
United Kingdom
Are you using ISO8859-1? Do you see © as copyright, ÷ as division and ½ as 1/2?
>But where is the guarantee that size_t fits into (unsigned long)??
>Suppose instead it requires (unsigned long long long) or some other
>such idiocy??
There is no type (unsigned long long long) in the standard. There
are only four unsigned integral types, unsigned long is the largest
of them and size_t must be one of them. So size_t does fit into unsigned
long.
Sorry, I don't have the standard at hand, so I can't cite chapter
and verse.
hp
--
_ | Peter J. Holzer | If I were God, or better yet
|_|_) | Sysadmin WSR | Linus, I would ...
| | | h...@wsr.ac.at | -- Bill Davidsen
__/ | http://wsrx.wsr.ac.at/~hjp/ | (davi...@tmr.com)
> co...@mcnc.org (Carlie Coats) writes:
>
> >But where is the guarantee that size_t fits into (unsigned long)??
> >Suppose instead it requires (unsigned long long long) or some other
> >such idiocy??
>
> There is no type (unsigned long long long) in the standard. There
> are only four unsigned integral types, unsigned long is the largest
> of them and size_t must be one of them. So size_t does fit into unsigned
> long.
>
> Sorry, I don't have the standard at hand, so I can't cite chapter
> and verse.
At least the ANSI version seems to be *very* vague on this. I had trouble
even finding a statement that says long must be at least as large as int.
(It may be in there, but then it's well hidden.)
One thing I definitely didn't find was "size_t must be one of them".
Again, it *might* be possible to reason this out from the standard, but it
is by no means obvious. However, I couldn't find a statement saying that
you can't have numbers too large for (unsigned) long.
If someone else can't find an obvious statement of these, then that seems
to be a defect - the standard should be more explicit about this.
Kai
--
Internet: k...@khms.westfalen.de
Bang: major_backbone!khms.westfalen.de!kai
http://www.westfalen.de/private/khms/
It isn't, exactly. All we get is
6.1.2.5 Types
.... "signed char, short int, int, long int".
[pp. 4]
"In the list of signed integer types above, the range
of values of each type is a subrange of the values of the
next type in the list."
>One thing I definitely didn't find was "size_t must be one of them".
7.1.6 Common definitions
"size_t
which is the unsigned integral type of the result of the sizeof
operator; ..."
6.1.2.5
"For each of the signed integer types, there is a corresponding (but
different) unsigned integer type..."
So size_t must be one of the four unsigned types.
I agree, it should be more explicit anyway.
-s
--
Peter Seebach - se...@solon.com - Copyright 1996 - http://www.solon.com/~seebs
Unix/C Wizard - send mail for help, or send money for consulting!
The *other* C FAQ, the hacker FAQ, et al. See web page above.
Unsolicited email (junk mail and ads) is unwelcome, and will be billed for.