P99 is a suite of macro and function definitions that ease programming in modern C, aka C99. By using new facilities in C99 we implement default arguments for functions, scope bound resource management, transparent allocation and initialization, ...
By using special features of some compilers and operating systems, we also are able to provide an almost feature complete emulation of the new C standard, C11.
In C, functions (whether
inline or not) and macros fulfill different purposes. Their difference should not be seen as ideological as some seem to take it, and what is even more important, they may work nicely together.
Macros are text replacement that is done at compile time and they can do things like P99_SIGNED(EXPR) which is defined by P99. That macro takes an expression as an argument, and tells at compile time of whether or not the integral type of
EXPR is signed or not. Additionally it guarantees that
EXPR itself is not evaluated at run time (so there are no side effects), but that only its type is taken into consideration.
Such an example shows that macros are ideally used when the type of an expression is to be determined and you want to act accordingly to that type. On the other hand, the pitfall with macros is that their arguments may be evaluated several times, which is bad because of side effects.
Functions on the other hand are typed, which makes them more strict or, phrased negatively, less flexible. Consider the function
It takes signed integer value
a and computes its absolute value. Observe that the return type of this function is unsigned. This has to be so, since otherwise not all valid values could be realized.
p00_abs_signed would not be a good candidate for a macro, since
a is evaluated twice in the expression; once in the controlling expression and once for returning its value or its negation.
We may use this function with any integral type, but then the result would probably not be what a naive programmer would expect if the argument is a large unsigned value. The argument will be promoted to
intmax_t. If the value
X that is passed to the call is positive and greater than
INTMAX_MAX = 2N -1, the result is probably not what we'd expect. 1 If the conversion to
intmax_t doesn't result in a range error thrown by the run time system (it would be permitted to do so), the argument a of the function would receive the negative value
2N - X. The result of the function call would then be
C and not
With the following macro we get rid of these restrictions by combining the macro and the function:
#define P99_ABS(EXPR) (P99_SIGNED(EXPR) ? p00_abs_signed(EXPR) : (EXPR))
This has the following properties
EXPRis evaluated exactly once.
In that spirit, P99 aims to provide utilities that often combine macros and
inline funcions and that are only possible with the features that come with C99 (read ANSI C as normalized in 1999) and that were absent in C89. The features include among others
On some platforms, P99 is also able to emulate the main features that come with the newest C standard, C11:
With all these features it implements utilities that previously had not been possible to program in C (or C macros) or that were very difficult to implement
P99 also provides numerous facilities for macro programming.
P99 is not a C library in the classical sense but merely a collection of include files:
N+1 is the width of
uintmax_t, assuming most common representations of signed integers.
2 Well, there is exactly one exception to that: on systems where
-INTMAX_MIN is not representable in
uintmax_t, this same value may cause problems.
The version this documentation describes can be identified via the macros P99_VERSION_DATE, namely Fri Mar 21 17:48:24 2014 +0100. It also is tagged with an hexadecimal ID tag that is given in P99_VERSION_ID, namely 25e980231040c940906813a487c6979d434c5888.
Copyright © 2010-2012 Jens Gustedt, INRIA, France, http://www.inria.fr/