tags:

views:

5354

answers:

6

I'm trying to print types like off_t and size_t. What is the correct placeholder for printf() that is portable?

Or is there a completely different way to print those variables?

A: 

Which version of C are you using?

In C90, the standard practice is to cast to signed or unsigned long, as appropriate, and print accordingly. I've seen %z for size_t, but Harbison and Steele don't mention it under printf(), and in any case that wouldn't help you with ptrdiff_t or whatever.

In C99, the various _t types come with their own printf macros, so something like "Size is " FOO " bytes." I don't know details, but that's part of a fairly large numeric format include file.

David Thornley
Jonathan Leffler
Fourth edition - should I update?
David Thornley
A: 

As I recall, the only portable way to do it, is to cast the result to "unsigned long int" and use %lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
James Curran
Should be "%lu", as the length modifier should come before the conversion.
dwc
off_t for example is a signed long long.
Georg
A: 

Looking at man 3 printf on Linux, OS X, and OpenBSD all show support for %z for size_t and %t for ptrdiff_t (for C99), but none of those mention off_t. Suggestions in the wild usually offer up the %u conversion for off_t, which is "correct enough" as far as I can tell (both unsigned int and off_t vary identically between 64-bit and 32-bit systems).

dwc
My system (OS X) has 32-bit `unsigned int` and 64-bit `off_t`. So the cast would cause data to be lost.
Dietrich Epp
+11  A: 

You can use z for size_t and t for ptrdiff_t like in

printf("%zd", size);

But my manpage says some older library used a different character than z and discourages use of it. Nevertheless, it's standardized (by the C99 standard). For those intmax_t and int8_t of stdint.h and so on, there are macros you can use, like another answer said:

printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);

They are listed in the manpage of inttypes.h.

Personally, I would just cast the values to unsigned long or long like another answer recommends. If you use C99, then you can (and should, of course) cast to unsigned long long or long long and use the %llu or %lld formats respectively.

Johannes Schaub - litb
Since PRId32 doesn't include the % format specifier, shouldn't that be`printf("value: %" PRId32, some_int32_t);`
Craig S
off_t is actually a signed long long on my system.
Georg
yeah for signed values you will have to convert to long or long long. this latter type does not exist in current C++ - but next version includes it. especially if you work with posix and it includes some types like off_t that have big sizes, you've to be careful.
Johannes Schaub - litb
then, i would use long long and proper formats if you know it supports long long. otherwise for embedded development where you know you only have to do with long as widest type, you can stick with long/unsigned long.
Johannes Schaub - litb
this question is about C. i forgot that. so i better mention in the answer that if you have long long available (as in c99) you should use that.
Johannes Schaub - litb
I think the man page discourages use of Z (uppercase) which was used by libc5. It doesn't seem to discourage z (lowercase).
Draemon
+1  A: 

You'll want to use the formatting macros from inttypes.h.

See this question: http://stackoverflow.com/questions/174612/cross-platform-format-string-for-variables-of-type-sizet

Michael Burr
It does not answer how to format off_t.
stepancheg
Assuming that off_t is a signed, pointer-sized int (I don't know what the precise definition is) like ptrdiff_t then you'd use PRIdPTR or PRIiPTR.
Michael Burr
The `off_t` type is larger than a pointer on any 32-bit system that supports large files (which is most 32-bit systems these days).
Dietrich Epp
A: 

use "%zo" for off_t. (octal) or "%zu" for decimal.

Shankar
%z is for size_t not off_t
Draemon