The code associated with the printf
family of functions
is generated from a special C template file that is customized after analysis of the user’s
C code.
Template files are shipped with the compiler and contain a full
implementation of printf
's functionality, but these features are
conditionally included based on how you use the functions in your project.
The compiler analyzes the C source code, searching for calls to
printf
family function and collates the format string placeholders that
were used in those calls.
For example, if a program contains one call to printf()
,
which looks like:
printf(”input is: %d”, input);
The compiler will note that only the %d
placeholder is
used and the printf()
function that is linked into the program might not
include code to handle printing of types other than an int
.
If the format string in a call to printf()
is a pointer
to a string, not a string literal as above, then the compiler will not be able to detect
how printf()
is used. A more complete version of printf()
will be generated; however, the compiler can still make certain assumptions. In particular,
the compiler can look at the number and type of the arguments to printf()
following the format string expression to determine which placeholders could be valid. This
enables the size and complexity of the generated printf()
routine to be
kept to a minimum even in this case.
For example, if printf()
was called as follows:
printf(myFormatString, 4, 6);
the compiler could determine that, for example, no floating-point placeholders are required.
No aspect of this operation is user-controllable (other than by adjusting
the calls to printf()
); however, the final printf()
code
can be observed by opening the pre-processed output of the printf()
modules.
Although the printf
family functions are generated with each
build, they are packaged into a library before they are used. This allows the functions to
be replaced by user-defined code in the usual way.