Functions belonging to the printf function family have the type specifiers "%p" and "%x".

"x" and "X" serve to output a hexadecimal number. "x" stands for lower case letters (abcdef) while "X" for capital letters (ABCDEF).

"p" serves to output a pointer. It may differ depending upon the compiler and platform.

One specifier is often used instead of another on 32-bit systems, but it is a mistake. Here is an example:

int a = 10; int *b = &a; printf("%p

",b); printf("%X

",b);

On a Win32 system, the following result will be printed:

0018FF20 18FF20

As you may see, the output results for "%p" and "%X" are rather similar. This similarity leads to inaccuracy in the code and this, in turn, results in errors occurring when you port a program to a 64-bit platform. Most often it is "%X" that is used instead of "%p" to output the value of a pointer, and this results in printing of an incorrect value if the object is situated outside the four less significant Gbytes of the address space. Let us consider the corresponding 64-bit version of this program:

size_t Gb = 1024*1024*1024; char *a = (char *)malloc(2 * Gb * sizeof(char)); char *b = (char *)malloc(2 * Gb * sizeof(char)); printf("use %%X: a=%X

", a); printf("use %%X: b=%X

", b); printf("use %%p: a=%p

", a); printf("use %%p: b=%p

", b); use %X: a=80000040 use %X: b=40010040 use %p: a=0000000080000040 use %p: b=0000000140010040

The pointer value "b" is printed incorrectly when using "%X".

Here is one more example. Although it looks strange, the code given here in an abridged form was used in a real application in the UNDO/REDO subsystem:

// Here the pointers were saved in the form of a string int *p1, *p2; .... char str[128]; sprintf(str, "%X %X", p1, p2); // In another function this string was processed // in this way: void foo(char *str) { int *p1, *p2; sscanf(str, "%X %X", &p1, &p2); // The result is incorrect values of pointers p1 and p2. ... }

Manipulation with the pointers using "%X" resulted in an incorrect program behavior on a 64-bit system. Note that such errors might occur very rarely. To diagnose these, and other similar flaws, it is a good idea to use the analyzer PVS-Studio.

References