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.