Borland C++ reference

printf

checked against scan

Writes formatted output to stdout.

Defined in header <stdio.h>

Syntax

#include <stdio.h>
int printf(const char *format[, argument, ...]);

Portability

DOSUNIXWindowsANSI CC++ only
■■■

Remarks

printf accepts a series of arguments, applies to each a format specifier contained in the format string given by format, and outputs the formatted data to stdout. There must be the same number of format specifiers as arguments.

The format string

The format string, present in each of the ...printf function calls, controls how each function will convert, format, and print its arguments. There must be enough arguments for the format; if there are not, the results will be unpredictable and likely disastrous. Excess arguments (more than required by the format) are merely ignored.

The format string is a character string that contains two types of objects — plain characters and conversion specifications:

  • Plain characters are simply copied verbatim to the output stream.
  • Conversion specifications fetch arguments from the argument list and apply formatting to them.

Format specifiers

...printf format specifiers have the following form:

% [flags] [width] [.prec] [F|N|h|l|L] type

Each conversion specification begins with the percent character (%). After the % come the following, in this order:

  • an optional sequence of flag characters, [flags]
  • an optional width specifier, [width]
  • an optional precision specifier, [.prec]
  • an optional input-size modifier, [F|N|h|l|L]
  • the conversion-type character, [type]

Optional format string components

These are the general aspects of output formatting controlled by the optional characters, specifiers, and modifiers in the format string:

Character or specifierWhat it controls or specifies
flagsOutput justification, numeric signs, decimal points, trailing zeros, octal and hex prefixes
widthMinimum number of characters to printpadding with blanks or zeros
precisionMaximum number of characters to print; for integers, minimum number of digits to print
sizeOverride default size of argument: N = near pointer, F = far pointer, h = short int, l = long, L = long double

...printf conversion-type characters

The following table lists the ...printf conversion-type characters, the type of input argument accepted by each, and in what format the output appears.

The information in this table of type characters is based on the assumption that no flag characters, width specifiers, precision specifiers, or input-size modifiers were included in the format specifier. To see how the addition of the optional characters and specifiers affects the ...printf output, refer to the tables following this one.

Type characterInput argumentFormat of output
Numerics
dintegersigned decimal int.
iintegersigned decimal int.
ointegerunsigned octal int.
uintegerunsigned decimal int.
xintegerunsigned hexadecimal int (with a, b, c, d, e, f).
Xintegerunsigned hexadecimal int (with A, B, C, D, E, F).
ffloating-pointsigned value of the form [-]dddd.dddd.
efloating-pointsigned value of the form [-]d.dddd or e [+/-]ddd.
gfloating-pointsigned value in either e or f form, based on given value and precision. Trailing zeros and the decimal point are printed only if necessary.
Efloating-pointSame as e, but with E for exponent.
Gfloating-pointSame as g, but with E for exponent if e format used.
Characters
ccharacterSingle character.
sstring pointerPrints characters until a null-terminator is pressed or precision is reached.
%noneThe % character is printed.
Pointers
npointer to intStores (in the location pointed to by the input argument) a count of the characters written so far.
ppointerPrints the input argument as a pointer; format depends on which memory model was used. It will be either XXXX:YYYY or YYYY (offset only).

Conventions

Certain conventions accompany some of these specifications, as summarized in the following table:

CharactersConventions
e or EThe argument is converted to match the style [-] d.ddd...e[+/-]ddd, where one digit precedes the decimal point; the number of digits after the decimal point is equal to the precision; the exponent always contains at least two digits.
fThe argument is converted to decimal notation in the style [-] ddd.ddd..., where the number of digits after the decimal point is equal to the precision (if a nonzero precision was given).
g or GThe argument is printed in style e, E or f, with the precision specifying the number of significant digits. Trailing zeros are removed from the result, and a decimal point appears only if necessary. The argument is printed in style e or f (with some restraints) if g is the conversion character, and in style E if the character is G. Style e is used only if the exponent that results from the conversion is either greater than the precision or less than −4.
x or XFor x conversions, the letters a, b, c, d, e, and f appear in the output; for X conversions, the letters A, B, C, D, E, and F appear.

Note: Infinite floating-point numbers are printed as +INF and −INF. An IEEE Not-a-Number is printed as +NAN or −NAN.

Flag characters

The flag characters are minus (-), plus (+), sharp (#), and blank ( ). They can appear in any order and combination.

FlagWhat it specifies
-Left-justifies the result, pads on the right with blanks. If not given, right-justifies result, pads on left with zeros or blanks.
+Signed conversion results always begin with a plus (+) or minus (-) sign.
blankIf value is nonnegative, the output begins with a blank instead of a plus; negative values still begin with a minus.
#Specifies that arg is to be converted using an "alternate form." See the following table.

Note: Plus (+) takes precedence over blank ( ) if both are given.

Alternate forms

If the # flag is used with a conversion character, it has the following effect on the argument (arg) being converted:

Conversion characterHow # affects arg
c,s,d,i,uNo effect.
o0 is prepended to a nonzero arg.
x or X0x (or 0X) is prepended to arg.
e, E, or fThe result always contains a decimal point even if no digits follow the point. Normally, a decimal point appears in these results only if a digit follows it.
g or GSame as e and E, with the addition that trailing zeros are not removed.

Width specifiers

The width specifier sets the minimum field width for an output value.

Width is specified in one of two ways: directly, through a decimal digit string, or indirectly, through an asterisk (*). If you use an asterisk for the width specifier, the next argument in the call (which must be an int) specifies the minimum output field width.

In no case does a nonexistent or small field width cause truncation of a field. If the result of a conversion is wider than the field width, the field is simply expanded to contain the conversion result.

Width specifierHow output width is affected
nAt least n characters are printed. If the output value has less than n characters, the output is padded with blanks (right-padded if − flag given, left-padded otherwise).
0nAt least n characters are printed. If the output value has less than n characters, it is filled on the left with zeros.
*The argument list supplies the width specifierwhich must precede the actual argument being formatted.

Precision specifiers

A precision specification always begins with a period (.) to separate it from any preceding width specifier. Then, like width, precision is specified either directly through a decimal digit string, or indirectly through an asterisk (*). If you use an asterisk for the precision specifier, the next argument in the call (treated as an int) specifies the precision.

If you use asterisks for the width or the precision, or for both, the width argument must immediately follow the specifiers, followed by the precision argument, then the argument for the data to be converted.

Precision specifierHow output precision is affected
(none given)Precision set to default: default = 1 for d, i, o, u, x, X types; default = 6 for e, E, f types; default = all significant digits for g, G types; default = print to first null character for s types; no effect on c types
.0For d, i, o, u, x types, precision set to default; for e, E, f types, no decimal point is printed.
.nn characters or n decimal places are printed. If the output value has more than n characters, the output might be truncated or rounded. (Whether this happens depends on the type character.)
*The argument list supplies the precision specifierwhich must precede the actual argument being formatted.

Note: If an explicit precision of zero is specified, and the format specifier for the field is one of the integer formats (that is, d, i, o, u, x), and the value to be printed is 0, no numeric characters will be output for that field (that is, the field will be blank).

Conversion characterHow precision specification (.n) affects conversion
d, i, o, u, x, X.n specifies that at least n digits are printed. If the input argument has less than n digits, the output value is left-padded with zeros. If the input argument has more than n digits, the output value is not truncated.
e, E, f.n specifies that n characters are printed after the decimal point, and the last digit printed is rounded.
g, G.n specifies that at most n significant digits are printed.
c.n has no effect on the output.
s.n specifies that no more than n characters are printed.

Input-size modifier

The input-size modifier character (F, N, h, l, or L) gives the size of the subsequent input argument:

  • F = far pointer
  • N = near pointer
  • h = short int
  • l = long
  • L = long double

The input-size modifiers (F, N, h, l, and L) affect how the ...printf functions interpret the data type of the corresponding input argument arg. F and N apply only to input args that are pointers (%p, %s, and %n). h, L, and L apply to input args that are numeric (integers and floating-point).

Both F and N reinterpret the input arg. Normally, the arg for a %p, %s, or %n conversion is a pointer of the default size for the memory model. F says "interpret arg as a far pointer." N says "interpret arg as a near pointer."

h, l, and L override the default size of the numeric data input arguments: l and L apply to integer (d, i, o, u, x, X) and floating-point (e, E, f, g, and G) types, while h applies to integer types only. Neither h nor l affect character (c, s) or pointer (p, n) types.

Input-size modifierHow arg is interpreted
Farg is read as a far pointer.
Narg is read as a near pointer. N cannot be used with any conversion in huge model.
harg is interpreted as a short int for d, i, o, u, x, or X.
larg is interpreted as a long int for d, i, o, u, x, or X; arg is interpreted as a double for e, E, f, g, or G.
Larg is interpreted as a long double for e, E, f, g, or G.

Return value

printf returns the number of bytes output. In the event of error, printf returns EOF.

See also

Example

#include <stdio.h>
#include <string.h>

#define I 555
#define R 5.5

int main(void)
{
   int i,j,k,l;
   char buf[7];
   char *prefix = buf;
   char tp[20];
   printf("prefix  6d      6o      8x        10.2e        "
          "10.2f\n");
   strcpy(prefix,"%");
   for (i = 0; i < 2; i++) {
      for (j = 0; j < 2; j++)
         for (k = 0; k < 2; k++)
            for (l = 0; l < 2; l++) {
               if (i==0)  strcat(prefix,"-");
               if (j==0)  strcat(prefix,"+");
               if (k==0)  strcat(prefix,"#");
               if (l==0)  strcat(prefix,"0");
               printf("%5s |",prefix);
               strcpy(tp,prefix);
               strcat(tp,"6d |");
               printf(tp,I);
               strcpy(tp,"");
               strcpy(tp,prefix);
               strcat(tp,"6o |");
               printf(tp,I);
               strcpy(tp,"");
               strcpy(tp,prefix);
               strcat(tp,"8x |");
               printf(tp,I);
               strcpy(tp,"");
               strcpy(tp,prefix);
               strcat(tp,"10.2e |");
               printf(tp,R);
               strcpy(tp,prefix);
               strcat(tp,"10.2f |");
               printf(tp,R);
               printf("  \n");
               strcpy(prefix,"%");
            }
      }
   return 0;
}

Program output

prefix  6d      6o      8x        10.2e        10.2f
%-+#0 |+555   |01053  |0x22b    |+5.50e+00  |+5.50      |
 %-+# |+555   |01053  |0x22b    |+5.50e+00  |+5.50      |
 %-+0 |+555   |1053   |22b      |+5.50e+00  |+5.50      |
  %-+ |+555   |1053   |22b      |+5.50e+00  |+5.50      |
 %-#0 |555    |01053  |0x22b    |5.50e+00   |5.50       |
  %-# |555    |01053  |0x22b    |5.50e+00   |5.50       |
  %-0 |555    |1053   |22b      |5.50e+00   |5.50       |
   %- |555    |1053   |22b      |5.50e+00   |5.50       |
 %+#0 |+00555 |001053 |0x00022b |+05.50e+00 |+000005.50 |
  %+# |  +555 | 01053 |   0x22b | +5.50e+00 |     +5.50 |
  %+0 |+00555 |001053 |0000022b |+05.50e+00 |+000005.50 |
   %+ |  +555 |  1053 |     22b | +5.50e+00 |     +5.50 |
  %#0 |000555 |001053 |0x00022b |005.50e+00 |0000005.50 |
   %# |   555 | 01053 |   0x22b |  5.50e+00 |      5.50 |
   %0 |000555 |001053 |0000022b |005.50e+00 |0000005.50 |
    % |   555 |  1053 |     22b |  5.50e+00 |      5.50 |

Differences from modern implementations

Draft. Items marked (manual) come from the 3.1 manual itself; the others are from general knowledge and not yet confirmed against the Borland run-time code.

  • int is 16 bits. %d, %u, %x and %o take a 16-bit int; use %ld/%lx for 32-bit long. Passing a long to %d puts two words on the stack and shifts every later argument. This is the most common source of garbage output when porting code.
  • F and N size modifiers (manual) select far or near pointers for %p, %s and %n. They don’t exist in modern C. %p prints XXXX:YYYY (segment:offset) for far pointers or YYYY for near ones (manual); glibc prints 0x… and MSVC prints a zero-padded hex address.
  • Infinity and NaN are printed as +INF, -INF, +NAN and -NAN, always signed and in upper case (manual). C99 prints inf/nan (INF/NAN for %E, %G, %F), with a sign only for negative values or with the + flag.
  • No C99 additions: no hh, ll, j, z, t length modifiers, no %a/%A (hex float) and no %F conversion. 32-bit long is the widest integer type.
  • printf returns the number of bytes output (manual). In text mode each \n becomes CR LF on the way to DOS; whether the return value counts the inserted CR is not stated. To be checked in the run-time code.
  • Not available in Windows programs: the portability table leaves the Windows column empty for printf (there is no stdout in a Windows GUI application). According to their extracted tables, sprintf and fprintf are marked for Windows.
  • The example’s output (manual, page 406) is identical to what glibc prints today for the same program, so the flags, width and precision handling of d, o, x, e and f match modern behaviour.

Modern references