printf() Specification for size_t?

D

David T. Ashley

What printf() format specifier will allow me to print a size_t integer?

Seems like it should be there, but couldn't find it in documentation.

I'm using %ul, but that might not work on every system, I think.

Thanks.
 
D

dj3vande

What printf() format specifier will allow me to print a size_t integer?

Seems like it should be there, but couldn't find it in documentation.

I'm using %ul, but that might not work on every system, I think.

For C90, cast it to unsigned long and use %lu:
--------
printf("The size_t value is %lu\n",(unsigned long)sz);
--------
If you have C99, use %zu.

Note that %lu and %ul are not the same.


dave
 
P

Peter Nilsson

David T. Ashley said:
What printf() format specifier will allow me to print
a size_t integer?

Under C90, you should use the largest (portable)
unsigned integer type, namely unsigned long...

printf("%lu\n", (unsigned long) sizeof x);

Under C99, you can use the length modifier z...

printf("%zu\n", sizeof x);
Seems like it should be there, but couldn't find
it in documentation.

I'm using %ul,

Which will print an unsigned int value followed by an
ell.
but that might not work on every
system, I think.

Using unsigned long (uncluding conversion) is reasonably
forwards compatible. That said, it's possible to cater
for both worlds with some conditional includes and macros,
but it generally isn't worth the hassle since it's
relatively rare to print a size_t without knowing limits
on how big the object that it refers to can reasonably
be.

For instance, if you're dealing with objects that might
be larger than 4G, then you're more likely to be printing
the size in megabytes or gigabytes. Either way the integer
calculation is likely to be in the range of an unsigned
long.
 
D

David T. Ashley

For C90, cast it to unsigned long and use %lu:

I had a brain malfunction. I actually used %lu, which worked fine, but
somehow in the newsgroup post I stated "%ul".

I'm aware that on my platform, "lu" works fine (naturally, I looked up the
size_t definition before I did this).

My only fear (and the reason I made the post) is that I could envision
platforms where the largest integer has far more bits than the address space
of the machine. I've never seen such a thing, but it seems it could exist.

In other words, I can't figure out why size_t _____necessarily_____ has any
relationship to the largest integer size.
 
D

David T. Ashley

Peter Nilsson said:
Using unsigned long (uncluding conversion) is reasonably
forwards compatible. That said, it's possible to cater
for both worlds with some conditional includes and macros,
but it generally isn't worth the hassle since it's
relatively rare to print a size_t without knowing limits
on how big the object that it refers to can reasonably
be.

For instance, if you're dealing with objects that might
be larger than 4G, then you're more likely to be printing
the size in megabytes or gigabytes. Either way the integer
calculation is likely to be in the range of an unsigned
long.

I had a brain malfunction. I actually used %lu, which worked fine, but
somehow in the newsgroup post I stated "%ul".

I'm aware that on my platform, "lu" works fine (naturally, I looked up the
size_t definition before I did this).

My only fear (and the reason I made the post) is that I could envision
platforms where the largest integer has far more bits than the address space
of the machine. I've never seen such a thing, but it seems it could exist.

In other words, I can't figure out why size_t _____necessarily_____ has any
relationship to the largest integer size.
 
M

Martin Ambuhl

David said:
What printf() format specifier will allow me to print a size_t integer?

Seems like it should be there, but couldn't find it in documentation.

I'm using %ul, but that might not work on every system, I think.

"%ul" should never work, while "%lu" often will.

If you have a library supporting the C99 specifier "%zu", use that.
Otherwise, you can't get much safer than
"%llu" with a cast to (unsigned long long)
If your implementation supports neither, then use
"%lu" with a cast to (unsigned long)
and pray.
 
R

Richard Heathfield

Martin Ambuhl said:
"%ul" should never work, while "%lu" often will.

I see no reason why %ul should not work. There is nothing to stop
implementors from using unsigned ints as the underlying type for size_t,
and there is nothing to stop programmers from putting an 'l' onto stdout
immediately after the size value.
 
K

Keith Thompson

David T. Ashley said:
I had a brain malfunction. I actually used %lu, which worked fine,
but somehow in the newsgroup post I stated "%ul".

I'm aware that on my platform, "lu" works fine (naturally, I looked up
the size_t definition before I did this).

My only fear (and the reason I made the post) is that I could envision
platforms where the largest integer has far more bits than the address
space of the machine. I've never seen such a thing, but it seems it
could exist.

In other words, I can't figure out why size_t _____necessarily_____
has any relationship to the largest integer size.

size_t is necessarily no bigger than the largest integer size.
There's no guarantee that it's the same as any particular predefined
integer type, which is why (unless you have "%zu") you have to convert
it to some type to print it.

In C90, the largest unsigned integer type (size_t is guaranteed to be
an unsigned type) is unsigned long, so this:

size_t size = <whatever>;
printf("size = %lu\n", (unsigned long)size);

should always work. In C99, unsigned long long isn't guaranteed to be
the widest unsigned integer type (an implementation can provide
extended integer types), and it's conceivable that size_t could be
wider than unsigned long. It's guaranteed that size_t is no wider
than uintmax_t, but since C99 provides formats for both size_t and
uintmax_t that isn't all that helpful.

If you need portability to both C90 and C99 implementations, you can
still use the "%lu" trick *if* you can guarantee that the particular
value you're printing is no greater than ULONG_MAX. Even if size_t is
wider than unsigned long, if the value doesn't exceed ULONG_MAX then
the cast performs a (narrowing) conversion that doesn't lose any
information. (Even if the value is greater than ULONG_MAX, the
semantics of unsigned types means that you'll just get an incorrect
result; there's no undefined behavior.)

If you know your code will run only under conforming C99
implementations, you can use "%zu" (and there's no need for a cast).
But note that, out in the real world, even testing for
__STDC_VERSION__ >= 199901L doesn't necessarily guarantee that "%zu"
will work. The __STDC_VERSION__ macro is set by the compiler; it's up
to the runtime library to implement printf properly. An
implementation combining a compiler and a runtime library *should* get
this right, but I think that some don't.
 
M

Martin Ambuhl

Richard said:
Martin Ambuhl said:


I see no reason why %ul should not work. There is nothing to stop
implementors from using unsigned ints as the underlying type for size_t,
and there is nothing to stop programmers from putting an 'l' onto stdout
immediately after the size value.

Thank you for your valuable contribution.
 
C

CBFalconer

Richard said:
Martin Ambuhl said:

I see no reason why %ul should not work. There is nothing to
stop implementors from using unsigned ints as the underlying
type for size_t, and there is nothing to stop programmers from
putting an 'l' onto stdout immediately after the size value.

I think this will create great confusion for newbies. It should be
labelled, etc. to attempt to avoid being taken too seriously.
 
V

vippstar

I think this will create great confusion for newbies. It should be
labelled, etc. to attempt to avoid being taken too seriously.
It would also confuse a newbie to think that %ul would print an
unsigned long.
When printf() encounters a % in the string literal, it searches for
one of the conversion specifiers, which are
d,i,a,u,x,X,f,F,e,E,g,G,a,A,c,s,p,n,%, and also parses any flag
characters, length modifiers, precision and field width which are
optional.
When not doing that, printf() simply puts the bytes to stdout.
So, according to that, %ul would be parsed as:
%: start parsing
u: valid conversion specifier. stop parsing
l: byte. put (write) to stdout

Hope this clears any confusion a newbie might had.

Reference: 7.19.6.1 ISO C99
 
A

Antoninus Twink

Martin Ambuhl said:


You're quite welcome, my dear chap!

Ouch! Twice the sarcasm cuts like a knife as we one again play "clc
regulars eating their own"...
 
P

pete

David said:
I had a brain malfunction.
I actually used %lu, which worked fine, but
somehow in the newsgroup post I stated "%ul".

That's why I call it (long unsigned) instead of (unsigned long).
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top