I need a portable way to print the value of a variable n of type size_t
. Since I use ANSI C89 I cannot use the z
length modifier. My current approach is to cast the value to long unsigned int
:
printf("%lu\n", (long unsigned int) n);
Provided that size_t
is defined as either unsigned int
or long unsigned int
I can't see how this would fail. Is the cast safe?
In C89, size_t
is defined as an unsigned integer type. Unlike future standards, C89 defines what the list of unsigned integer types are as the following:
As such, size_t
in C89 will never be larger than unsigned long
, and therefore the cast is always safe - both in that it will not cause any undefined behaviour and in that it will always be large enough to hold the value in entirety.
Worth noting; the C89 standard states: "A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program" Meaning that no extension could change this behaviour - while still conforming to the C89 standard, as the unsigned integer types have been specifically listed and therefore cannot be altered.
In future standards, this is not a guarantee and while you will not get undefined behaviour - you may lose data where unsigned long
is smaller than size_t
, meaning that you would display incorrect data to your user. In this situation I'd be hesitant to label it as "safe".
As an important additional note; this answer refers to compilers that are compliant with the C89 standard. It is possible for your C89 compiler to be "less than compliant" in the respects above, in which case - treat the behaviour to be similar to that of C99 or newer where you will not see undefined behaviour, but may suffer data loss if size_t
is larger than unsigned long
. To be clear though, this would not be complying with the C89 standard.
Beyond this, while my interpretation of the standard (1.7 Compliance) is that while it states extensions must not alter the behaviour of a "strictly conforming program" and as such cannot alter the fact that size_t
must be unsigned long
at largest without complying; it does not change the fact that such extensions do exist. For example GNU GCC does provide an extension that adds unsigned long long
. In my view this is non-compliant, but the reality is you must be prepared to deal with such things and as such - while the standard says what you are doing is completely safe, you must be prepared for potential data loss where non-compliant compilers or extensions are used.
Please see here for previous discussion on this topic: https://stackoverflow.com/a/39441237/955340