...
Furthermore, the definition of user programmer-defined types may change. This creates a problem using these types with formatted output functions (such as printf()
) and formatted input functions (such as scanf()
) (see FIO00-A. Take care when creating format strings).
The C99 intmax_t
and uintmax_t
types are capable of representing any value representable by any other integer types of the same signedness. This allows conversion between user programmer-defined integer types (of the same signedness) and intmax_t
and uintmax_t
. For example:
...
Formatted input and output functions contain a length modifier which provides the above facilities for input/output. The j
length modifier in a format string indicates that the following d
, i
, o
, u
, x
, X
, or n
conversion specifier will apply to an argument with type intmax_t
or uintmax_t
. C99 also specifies the z
length modifier for use with arguments of type size_t
, and the t
length modifier for arguments of type ptrdiff_t
.
The C99 intmax_t
and uintmax_t
can safely be used to perform formatted I/O with programmer-defined integer types. Convert signed programmer-defined integer types to intmax_t
and unsigned programmer-defined integer types to uintmax_t
, then output using the j
length modifier. Similarly, input programmer-defined integer types into variables of intmax_t
or uintmax_t
(whichever matches the signedness of the programmer-defined integer type) and then convert to the programmer-defined integer types using appropriate range checks.
There is no requirement that an implementation provide format length modifiers for implementation-defined integer types. For example, a machine with an implementation-defined 48-bit integer type might not bother to provide format length modifiers for the type. Such a machine would still have to have a 64-bit long long
, with intmax_t
being at least that large. So, this solution can be applied even if there are no format length modifiers for the 48-bit integers.
This rule is closely related to INT00-A. Understand the data model used by your implementation(s).
Non-Compliant Code Example (printf()
)
...
Compliant Solution (printf()
)
The C99 intmax_t
and uintmax_t
can safely be used to perform formatted I/O with programmer-defined integer types. Convert signed programmer-defined integer types to intmax_t
and unsigned programmer-defined integer types to uintmax_t
, then output using the j
length modifier. Similarly, input programmer-defined integer types into variables of intmax_t
or uintmax_t
(whichever matches the signedness of the programmer-defined integer type) and then convert to the programmer-defined integer types using appropriate range checks.
This compliant solution guarantees that the correct value of x
is printed, regardless of its length, provided that mytypedef_t
is an unsigned type.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <inttypes.h> /* ... */ mytypedef_t x; /* ... */ printf("%ju", (uintmax_t) x); |
There is no requirement that an implementation provides format length modifiers for implementation-defined integer types. For example, a machine with an implementation-defined 48-bit integer type might not bother to provide format length modifiers for the type. Such a machine would still have to have a 64-bit long long
, with intmax_t
being at least that large. So, this solution can be applied even if there are no format length modifiers for the 48-bit integers.
Non-Compliant Code Example (scanf()
)
...