Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changes between Initial Version and Version 1 of Printf


Ignore:
Timestamp:
2012-07-03T14:03:28Z (8 years ago)
Author:
Vojtech Horky
Comment:

Initial commit

Legend:

Unmodified
Added
Removed
Modified
  • Printf

    v1 v1  
     1= Using `printf` in a safe way =
     2
     3To ensure portability among different architectures (namely between 32bit and 64bit), do not use generic directives (e.g. `%d`) for printing types with fixed width or for user-defined types. Use HelenOS-specific macros - such as `PRIu32` (unsigned integer, 32bits) - instead.
     4
     5These macros hide the type modifier only, you can provide width specification and you must enter the leading percentile sign.
     6
     7The `PRI*` macros are defined in two places `/common.h` (yes, in the root directory of HelenOS source) and in `/uspace/lib/c/arch/ARCHITECTURE/include/inttypes.h`. `common.h` is a generated file that appears after you configure your build.
     8
     9== Fixed width ==
     10
     11The macro is of from `PRI<kind><width>`. `<width>` is one of 8, 16, 32 or 64 or `n` for native width. `<kind>` is summarized in following table.
     12
     13||= `<kind>` =||= Meaning =||
     14|| `u` || unsigned integer, decimal ||
     15|| `d` || signed integer, decimal ||
     16|| `x` || unsigned integer, hexadecimal ||
     17|| `o` || unsigned integer, octal ||
     18
     19== Handles ==
     20
     21Although handles in HelenOS have their own `typedef`, they are usually backed by integer or pointer. Integers are usually used for handles passed from servers to clients (e.g. devices, files). Typically, they use unsigned integer of the native size.
     22Pointers are used for structures used only locally (same application) and are used to hide implementation details.
     23
     24Thus, for these handles one should use `PRIun` (makes more sense for integer backed handles) or `PRIxn` (usually for pointers).
     25
     26
     27== Other ==
     28
     29Following table lists common types and allowed (recommended) ways of printing them.
     30
     31||= Type =||= Directive =||
     32|| `size_t` || `"%zu"` ||
     33|| `sysarg_t` || `PRIun` / `PRIxn` ||
     34|| `uintptr_t` || `"%#" PRIxn` ||
     35
     36== Annotating your own printf-like functions ==
     37
     38If you are creating your own `printf`-like function, do not forget to add `PRINTF_ATTRIBUTE()` to it to force checking of the parameters.
     39{{{
     40#!c
     41void my_logging_function(int level, const char *format, ...)
     42    PRINTF_ATTRIBUTE(2, 3);
     43// 2 .. second argument is the format string
     44// 3 .. the variadic arguments are here (third parameter)
     45}}}
     46
     47
     48== Example ==
     49
     50{{{
     51#!c
     52devman_handle_t device_handle;
     53printf("Handle = %" PRIun ".\n", device_handle);
     54
     55fid_t fibril_handle;
     56printf("Fibril handle = %#" PRIxn ".\n", fibril_handle);
     57
     58uint32_t pci_register;
     59printf("Register at 0x%08" PRIx32 ".\n", pci_register);
     60
     61int16_t small_value;
     62printf("16bits: %" PRId16 ".\n", small_value);
     63
     64sysarg_t ipc_argument;
     65printf("IPC  arg1 = %20" PRIun ".\n", ipc_argument);
     66
     67size_t buffer_size;
     68printf("Buffer has %zuB.\n", buffer_size);
     69
     70uintptr_t pointer_as_number;
     71printf("Data at %p or at %#" PRIxn ".\n", (void *) pointer_as_number, pointer_as_number);
     72
     73void *pointer;
     74printf("Pointer is built-in: %p.\n", pointer);
     75}}}
     76
     77
     78