As a kernel developer you'll probably find yourself treating the 'printk' function as a drop-in replacement for the 'printf' function provided by any useful C library such as uclibc or glibc - After all, it's usage is virtually the same. It was for this reason that I found my self naively surprised when reading the source for the kernel's implementation - I was surprised because it offers many more features than the typical C libraries' implementation. As I was unable to find any useful documentation on this - I thought I'd provide a brief overview.
Let's start with the typical '%p' type format specifier - we usually use it for printing the address of a pointer. However if you take a peek at the 'pointer' function in lib/vsprintf.c you'll notice that you can further specify the pointer type to print additional information. We'll look at some examples.
printk("%pf %pF\n", ptr, ptr) will print:
module_start module_start+0x0/0x62 [hello]
So where ptr is a function pointer, the %pF and %pf format specifiers will print the symbolic name of the function with or without an offset. In order to make use of this you need to ensure your kernel is compiled with support for CONFIG_KALLSYMS - This adds a symbol table to the kernel.
How about this one:
printk("%pM %pm\n", mac, mac) will print:
So where mac refers to a MAC address, the %pM and %pm format specifiers will nicely print the MAC address with or without colons between bytes.
printk("%pI4 %pi64\n", ip, ip) will print:
So where ip refers to an IP address, the %pI and %pi format specifiers will nicely print the IP address. The 4 suffix specifies the address is an IPv4 address - the 6 suffix for IPv6 address could also be used instead. In the case of IPv4 addresses the difference between an upper and lower case 'I' determines if leading zeros should be used (only in the most recent of kernels). In the case of IPv6 addresses the capitalization determines if colons are used or not.
So if you find yourself writing a network driver, debugging something with function pointers or wondering why stack traces don't contain symbols then these format specifiers may come in useful. For more information, and the full extent of the extended format specifiers (there are more), the best place to look is the code. Happy Coding.