Blame docs/PrintFormatSpecifiers.md

Packit 1fb8d4
# Print Format Specifiers
Packit 1fb8d4
Packit 1fb8d4
## Lookup Table
Packit 1fb8d4
Packit 1fb8d4
We use the following format specifiers for all \*printf\* and WLog_* functions:
Packit 1fb8d4
Packit 1fb8d4
| Type               | signed    | unsigned  | octal     | hex       | HEX       |
Packit 1fb8d4
| ------------------ | --------- | --------- | --------- | --------- | --------- |
Packit 1fb8d4
| signed char        | %hhd      |           |           |           |           |
Packit 1fb8d4
| unsigned char      |           | %hhu      | %hho      | %hhx      | %hhX      |
Packit 1fb8d4
| short              | %hd       |           |           |           |           |
Packit 1fb8d4
| unsigned short     |           | %hu       | %ho       | %hx       | %hX       |
Packit 1fb8d4
| int                | %d        |           |           |           |           |
Packit 1fb8d4
| unsigned int       |           | %u        | %o        | %x        | %X        |
Packit 1fb8d4
| long               | %ld       |           |           |           |           |
Packit 1fb8d4
| unsigned long      |           | %lu       | %lo       | %lx       | %lX       |
Packit 1fb8d4
| long long          | %lld      |           |           |           |           |
Packit 1fb8d4
| unsigned long long |           | %llu      | %llo      | %llx      | %llX      |
Packit 1fb8d4
| size_t             |           | %"PRIuz"  | %"PRIoz"  | %"PRIxz"  | %"PRIXz"  |
Packit 1fb8d4
| INT8               | %"PRId8"  |           |           |           |           |
Packit 1fb8d4
| UINT8              |           | %"PRIu8"  | %"PRIo8"  | %"PRIx8"  | %"PRIX8"  |
Packit 1fb8d4
| BOOLEAN            |           | %"PRIu8"  | %"PRIo8"  | %"PRIx8"  | %"PRIX8"  |
Packit 1fb8d4
| BYTE               |           | %"PRIu8"  | %"PRIo8"  | %"PRIx8"  | %"PRIX8"  |
Packit 1fb8d4
| CHAR               | %"PRId8"  |           |           |           |           |
Packit 1fb8d4
| UCHAR              |           | %"PRIu8"  | %"PRIo8"  | %"PRIx8"  | %"PRIX8"  |
Packit 1fb8d4
| INT16              | %"PRId16" |           |           |           |           |
Packit 1fb8d4
| UINT16             |           | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
Packit 1fb8d4
| WORD               |           | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
Packit 1fb8d4
| WCHAR              |           | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
Packit 1fb8d4
| SHORT              | %"PRId16" |           |           |           |           |
Packit 1fb8d4
| USHORT             |           | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
Packit 1fb8d4
| INT32              | %"PRId32" |           |           |           |           |
Packit 1fb8d4
| UINT32             |           | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| INT                | %"PRId32" |           |           |           |           |
Packit 1fb8d4
| UINT               |           | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| LONG               | %"PRId32" |           |           |           |           |
Packit 1fb8d4
| HRESULT            | %"PRId32" |           |           | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| NTSTATUS           | %"PRId32" |           |           | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| ULONG              |           | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| DWORD              |           | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| DWORD32            |           | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
Packit 1fb8d4
| BOOL               | %"PRId32" |           |           |           |           |
Packit 1fb8d4
| INT64              | %"PRId64" |           |           |           |           |
Packit 1fb8d4
| LONG64             | %"PRId64" |           |           |           |           |
Packit 1fb8d4
| LONGLONG           | %"PRId64" |           |           |           |           |
Packit 1fb8d4
| UINT64             |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
| ULONG64            |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
| ULONGLONG          |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
| DWORDLONG          |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
| QWORD              |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
| ULONG64            |           | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
## Pointers
Packit 1fb8d4
Packit 1fb8d4
When printing pointers you should cast the argument to ``(void*)``:
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
rdpContext *pContext;
Packit 1fb8d4
fprintf(stderr, "rdp context is %p\n", (void*) pContext);
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
If you need more formatting options cast the pointer argument to `size_t` and use
Packit 1fb8d4
any %"PRI*z" format specifier:
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
rdpContext *pContext;
Packit 1fb8d4
fprintf(stderr, "rdp context is %" PRIuz " (0x%" PRIXz ")\n", (size_t) pContext, (size_t) pContext);
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
## Integer Promotion
Packit 1fb8d4
Packit 1fb8d4
Remember that integer types smaller than int are promoted when an operation is
Packit 1fb8d4
performed on them.
Packit 1fb8d4
Packit 1fb8d4
Wrong:
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
UINT8 a, b;
Packit 1fb8d4
fprintf(stderr, "a - b is %" PRIu8 "\n", a - b);
Packit 1fb8d4
// depending on the system's PRIu8 definition you might get:
Packit 1fb8d4
// warning: format specifies type 'unsigned char' but the argument has type 'int'
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
Correct:
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
UINT8 a, b;
Packit 1fb8d4
fprintf(stderr, "a - b is %d\n", a - b);
Packit 1fb8d4
// or ...
Packit 1fb8d4
fprintf(stderr, "a - b is %" PRIu8 "\n", (UINT8) (a - b));
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
## TCHAR
Packit 1fb8d4
Packit 1fb8d4
When using `_tprintf` or similar TCHAR formatting functions or macros you
Packit 1fb8d4
need to enclose the PRI format defines:
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
LPCTSTR lpFileName1;
Packit 1fb8d4
UINT64 fileSize1;
Packit 1fb8d4
Packit 1fb8d4
_tprintf(_T("The size of %s is %") _T(PRIu64) _T("\n"), lpFileName1, fileSize1);
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
Since this makes the strings a lot harder to read try to avoid _tprintf if the
Packit 1fb8d4
arguments don't contain TCHAR types.
Packit 1fb8d4
Packit 1fb8d4
Note: If all compilers were C99 compliant we could simply write ...
Packit 1fb8d4
Packit 1fb8d4
```c
Packit 1fb8d4
_tprintf(_T("The size of %s is %") PRIu64 "\n"), lpFileName1, fileSize1);
Packit 1fb8d4
```
Packit 1fb8d4
Packit 1fb8d4
... since the standard says that only one of the character sequences must be
Packit 1fb8d4
prefixed by an encoding prefix and the rest of them are treated to have the
Packit 1fb8d4
same. However, Microsoft Visual Studio versions older than VS 2015 are not C99
Packit 1fb8d4
compliant in this regard.
Packit 1fb8d4
Packit 1fb8d4
See [How to use stdint types with _tprintf in Visual Studio 2013](http://stackoverflow.com/questions/41126081/how-to-use-stdint-types-with-tprintf-in-visual-studio-2013)
Packit 1fb8d4
for more information.
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
## Links
Packit 1fb8d4
Packit 1fb8d4
- [[MS-DTYP] 2.2 Common Data Types](https://msdn.microsoft.com/en-us/library/cc230309.aspx)
Packit 1fb8d4
- [Understand integer conversion rules](https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules)
Packit 1fb8d4
- [Printf format strings](https://en.wikipedia.org/wiki/Printf_format_string)
Packit 1fb8d4
- [C data types - Basic Types](https://en.wikipedia.org/wiki/C_data_types#Basic_types)