size_t n = foo();
printf("%lu\n", (long unsigned int) n);
Provided that size_t
is defined as either unsigned int
or long unsigned int
... Is the cast safe?
Yes, the cast is safe with no undefined behavior nor loss of information on C89, C99, C11.
But what happens if that proviso is not true?
Assuming the range of size_t
will be within the range of unsigned long
is very reasonable. Add a compile time test: ref
#include <limits.h>
#if defined(__STDC__)
#if defined(__STDC_VERSION__)
#if (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
#if SIZE_MAX > ULONG_MAX
#error Re-work printf size code
#endif
#endif
#endif
#endif
The point is that when code had a dependency - add a test. Even if it acceptable on all known machines today and historically, the future has unknowns.
C, today, with its immense flexibility does allow SIZE_MAX > ULONG_MAX
, but it is certainly rare. IMO, SIZE_MAX > ULONG_MAX
is beyond the pale.
Such tests are common as from time to time, though possible, it is simply not practicable or budgeted to write super portable code.
#include <limits.h>
#if CHAR_BIT != 8 && CHAR_BIT != 16 && CHAR_BIT != 32 && CHAR_BIT != 64
#error Code depends on char size as a common power of 2.
#endif
I need a portable way to print the value of a variable n of type size_t.
Yet to address OP's top level goal, a simple portable helper function can be written.
// This approach works with any unsigned type
void print_size_t(size_t n) {
if (n >= 10) print_size_t(n/10);
putchar((int) (n%10) + '0');
}
To avoid recursion, a slightly longer function:
#include <limits.h>
void print_size_t(size_t n) {
char buf[sizeof n * CHAR_BIT / 3 + 2]; // 1/3 is more than log2(10)
char *p = &buf[sizeof buf - 1]; // Start at end of buf[]
*p = '\0';
do {
p--;
*p = (char) (n%10 + '0');
n /= 10;
} while (n); // Use a do {} while so print_size_t(0) prints something
fputs(p, stdout);
}