Printf tricks
Printf Tricks
It may be old-fashioned, but I still find
printf (and sprintf and
_vsnprintf) incredibly useful, both for
printing debug output and for generating formatted strings.
Here are a few lesser-known formats that I use again and again. See MSDN for the full reference.
%04x - 4-digit hex number with leading zeroes
A quick review of some of the basics.
%x prints an int in hexadecimal.
%4x prints a hex int, right-justified to 4
places. If it's less than 4 digits, it's preceded by spaces.
If it's more than 4 digits, you get the full number.
%04x prints a hex int, right-justified to 4
places. If it's less than 4 digits, it's preceded by zeroes.
If it's more than 4 digits, you get the full number, but no
leading zeroes.
Similarly, %d prints a
signed int in decimal, and
%u prints an unsigned int in
decimal.
Not so similarly, %c prints a character and
%s prints a string. For wide (Unicode) strings,
prefix with l (ell, or w):
%lc and %ls.
Note: For the Unicode variants, such as
wprintf and friends, %c and
%s print wide strings. To force a narrow
string, no matter which variant, use the
%h size prefix, and to force a wide string, use
the %l size prefix; e.g., %hs and
%lc.
%p - pointer
The wrong way to print a pointer is to use
%x. The right way is to use %p.
It's portable to Win64, as well as to all other operating
systems.
Everyone should know this one, but many don't.
%I64d, %I64u, %I64x - 64-bit integers
To print 64-bit numbers (__int64), use the
I64 size prefix.
%Iu, %Id, %Ix - ULONG_PTR
ULONG_PTR, LONG_PTR, and
DWORD_PTR
are numeric types that are as wide as a pointer. In other
words, they map to
ULONG, LONG, and
DWORD
respectively on Win32, and
ULONGLONG, LONGLONG, and
ULONGLONG
on Win64.
The I size prefix (capital-i, not lowercase-L)
is what you need to print *LONG_PTR on Win32
and Win64.
%*d - runtime width specifier
If you want to calculate the width of a field at runtime,
you can use %*. This says the next argument is
the width, followed by whatever type you want to print.
For example, the following can be used to print a tree:
void Tree::Print(Node* pNode, int level)
{
if (NULL != pNode)
{
Print(pNode->Left, level+1);
printf("%*d%s\n", 2 * level, pNode->Key);
Print(pNode->Right, level+1);
}
}
%.*s - print a substring
With a variable precision, you can print a substring, or
print a non-NUL-terminated string, if you know its length.
printf("%.*s\n", sublen, str) prints the first
sublen characters of str.
[2005/7/19: fixed a typo in previous sentence (%.s
-> %.*s). A little elaboration on the
syntax: . in a printf format specification is
followed by the precision. For strings, the
precision specificies how many characters will be printed. A
precision of * indicates that the precision is
the next argument on the stack. If the precision is zero,
then nothing is printed. If a string has a precision
specification, its length is ignored.]
%.0d - print nothing for zero
I've occasionally found it useful to suppress output when a
number is zero, and %.0d is the way to do it.
(If you attempt to print a non-zero number with this
zero-precision specifier, it will be printed.) Similarly,
%.0s swallows a string.
%#x - print a leading 0x
If you want printf to automatically generate
0x before hex numbers, use
%#x instead of %x.
Other tricks
See the documentation for other useful tricks.
Security
Never use an inputted string as the format argument:
printf(str). Instead, use
printf("%s", str). The former is a stack
smasher waiting to happen.
%n is dangerous and disabled by default in
VS2005.
Don't use sprintf. Use the counted version,
_snprintf or _vsnprintf instead.
Better still, use the
StrSafe.h functions, StringCchPrintf and
StringCchVPrintf, to guarantee that your
strings are NUL-terminated.
[Update: 2008/01/25: See also Printf %n.]