Library Features Added by C99

Library Features Added by C99
The C99 Standard added features to the C library two ways. First, it added functions to headers previously defined by C89. For example, significant additions were made to the mathematics library supported by the <math.h> header. These additional functions were covered in the preceding chapters. Second, new categories of functions, ranging from support for complex arithmetic to type-generic macros, were created, along with new headers to support them. These new library elements are described in this chapter. Keep in mind that none of the features described here are supported by C++.

The Complex Library

C99 adds complex arithmetic capabilities to C. At the outset, it is important to state that the C99 complex math library differs completely from the complex class library defined by C++. If you will be programming in C++, you will want to use the C++ complex library. The C99 complex library is appropriate only for programmers restricted to the C language.
The C99 complex library is supported by the <complex.h> header. The following macros are defined:
Macro
Expands To
complex
_Complex
imaginary
_Imaginary
_Complex_I
(const float _Complex) i
_Imaginary_I
(const float _Imaginary) i
I
_Imaginary_I (or _Complex_I if imaginary types are not supported)
Here, i represents the imaginary value, which is the square root of –1. Support for imaginary types is optional.
_Complex and _Imaginary, rather than complex and imaginary, were specified as a keywords by C99 because many existing C89 programs had already defined their own custom complex data types using the names complex and imaginary. By using the keywords _Complex and _Imaginary, C99 avoids breaking preexisting code. For new programs, however, it is best to include <complex.h> and then use the complex and imaginary macros.
The complex math functions are shown below. Notice that float complex, double complex, and long double complex versions of each function are defined. The float complex version uses the suffix f, and the long double complex version uses the suffix l. Also, angles are in radians.
Function
Description
float cabsf(float complex arg);
double cabs(double complex arg);
long double cabsl(long double complex arg);
Returns the complex absolute value of arg
float complex cacosf(float complex arg);
double complex cacos(double complex arg);
long double complex cacosl(long double
                                              complex arg);
Returns the complex arc cosine of arg
float complex cacoshf(float complex arg);
double complex cacosh(double complex arg);
long double complex cacoshl(long double
                                                 complex arg);
Returns the complex arc hyperbolic cosine of arg
float cargf(float complex arg);
double carg(double complex arg);
long double cargl(long double complex arg);
Returns the phase angle of arg
float complex casinf(float complex arg);
double complex casin(double complex arg);
long double complex casinl(long double
                                              complex arg);
Returns the complex arc sine of arg
float complex casinhf(float complex arg);
double complex casinh(double complex arg);
long double complex casinhl(long double
                                                complex arg);
Returns the complex arc hyperbolic sine of arg
float complex catanf(float complex arg);
double complex catan(double complex arg);
long double complex catanl(long double
                                              complex arg);
Returns the complex arc tangent of arg
float complex catanhf(float complex arg);
double complex catanh(double complex arg);
long double complex catanhl(long double
                                                complex arg);
Returns the complex arc hyperbolic tangent of arg
float complex ccosf(float complex arg);
double complex ccos(double complex arg);
long double complex ccosl(long double
                                            complex arg);
Returns the complex cosine of arg
float complex ccoshf(float complex arg);
double complex ccosh(double complex arg);
long double complex ccoshl(long double
                                              complex arg);
Returns the complex hyperbolic cosine of arg
float complex cexpf(float complex arg);
double complex cexp(double complex arg);
long double complex cexpl(long double
                                             complex arg);
Returns the complex value earg, where e is the natural
logarithm base
float cimagf(float complex arg);
double cimag(double complex arg);
long double cimagl(long double complex arg);
Returns the imaginary part of arg
float complex clogf(float complex arg);
double complex clog(double complex arg);
long double complex clogl(long double
                                            complex arg);
Returns the complex natural logarithm of arg
float complex conjf(float complex arg);
double complex conj(double complex arg);
long double complex conjl(long double
                                            complex arg);
Returns the complex conjugate of arg
float complex cpowf(float complex a,
                                   long double complex b);
double complex cpow(double complex a,
                                     double complex b);
long double complex cpowl(long double complex a,
                                              long double complex b);
Returns the complex value of ab
float complex cprojf(float complex arg);
double complex cproj(double complex arg);
long double complex cprojl(long double
                                             complex arg);
Returns the projection of arg onto the Riemann sphere
float crealf(float complex arg);
double creal(double complex arg);
long double creall(long double complex arg);
Returns the real part of arg
float complex csinf(float complex arg);
double complex csin(double complex arg);
long double complex csinl(long double
                                           complex arg);
Returns the complex sine of arg
float complex csinhf(float complex arg);
double complex csinh(double complex arg);
long double complex csinhl(long double
                                              complex arg);
Returns the complex hyperbolic sine of arg
float complex csqrtf(float complex arg);
double complex csqrt(double complex arg);
long double complex csqrtl(long double
                                             complex arg);
Returns the complex square root of arg
float complex ctanf(float complex arg);
double complex ctan(double complex arg);
long double complex ctanl(long double
                                            complex arg);
Returns the complex tangent of arg
float complex ctanhf(float complex arg);
double complex ctanh(double complex arg);
long double complex ctanhl(long double
                                              complex arg);
Returns the complex hyperbolic tangent of arg

The Floating-Point Environment Library

In the header <fenv.h>, C99 declares functions that access the floating-point environment. These functions are shown in the following table:
Function
Description
void feclearexcept(int ex);
Clears the exceptions specified by ex.
void fegetexceptflag(fexcept_t *fptr,
                                   int ex);
The state of the floating-point exception flags specified by ex are stored in the variable pointed to by fptr.
void feraiseexcept(int ex);
Raises the exceptions specified by ex.
void fesetexceptflag(const fexcept_t *fptr,
                                  int ex);
Sets the floating-point status flags specified by ex to the state of the flags in the object pointed to by fptr.
int fetestexcept(int ex);
Bitwise ORs the exceptions specified in ex with the current floating-point status flags and returns the result.
int fegetround(void);
Returns a value that indicates the current rounding direction.
int fesetround(int direction);
Sets the current rounding direction to that specified by direction. A return value of zero indicates success.
void fegetenv(fenv_t *envptr);
The object pointed to by envptr receives the floating-point environment.
int feholdexcept(fenv_t *envptr);
Causes nonstop floating-point exception handling to be used. It also stores the floating-point environment in the variable pointed to by envptr and clears the status flags. It returns zero if successful.
void fesetenv(const fenv_t *envptr);
Sets the floating-point environment to that pointed to by envptr, but does not raise floating-point exceptions. This object must have been obtained by calling either fegetenv( ) or feholdexcept( ).
void feupdateenv(const fenv_t *envptr);
Sets the floating-point environment to that pointed to by envptr. It first saves any current exceptions, and raises these exceptions after the environment pointed to by envptr has been set. The object pointed to by envptr must have been obtained by calling either fegetenv( ) or feholdexcept( ).
The <fenv.h> header also defines the types fenv_t and fexcept_t, which represent the floating-point environment and the floating-point status flags, respectively. The macro FE_DFL_ENV specifies a pointer to the default floating-point environment defined at the start of program execution.
The following floating-point exception macros are defined:
FE_DIVBYZERO
FE_INEXACT
FE_INVALID
FE_OVERFLOW
FE_UNDERFLOW
FE_ALL_EXCEPT
Any combination of these macros can be stored in an int object by ORing them together.
The following rounding-direction macros are defined:
FE_DOWNWARD
FE_TONEAREST
FE_TOWARDZERO
FE_UPWARD
These macros indicate the method that is used to round values.
In order for the floating-point environment flags to be tested, the pragma FENV_ACCESS will need to be set to the on position. Whether floating-point flag access is on or off by default is implementation-defined.

The <stdint.h> Header

The C99 header <stdint.h> does not declare any functions, but it does define a large number of integer types and macros. The integer types are used to declare integers of known sizes or that manifest a specified trait.
Macros of the form intN_t specify an integer with N bits. For example, int16_t specifies a 16-bit signed integer. Macros of the form uintN_t specify an unsigned integer with N bits. For example, uint32_t specifies a 32-bit unsigned integer. Macros with the values 8, 16, 32, and 64 for N will be available in all environments that offer integers in these widths.
Macros of the form int_leastN_t specify an integer with at least N bits. Macros of the form uint_leastN_t specify an unsigned integer with at least N bits. Macros with the values 8, 16, 32, and 64 for N will be available in all environments. For example, int_least16_t is a valid type.
Macros of the form int_fastN_t specify the fastest integer type that has at least N bits. Macros of the form uint_fastN_t specify the fastest unsigned integer type that has at least N bits. Macros with the values 8, 16, 32, and 64 for N will be available in all environments. For example, int_fast32_t is valid in all settings.
The type intmax_t specifies a maximum-sized signed integer and the type uintmax_t specifies a maximum-sized unsigned integer.
Also defined are the intptr_t and uintptr_t types. These can be used to create integers that can hold pointers. These types are optional.
<stdint.h> defines several function-like macros that expand into constants of a specified integer type. These macros have the following general forms:
       INTN_C(value)
       UINTN_C(value)
where N is the bit width of the desired type. Each macro creates a constant that has at least N bits that contains the specified value.
Also defined are the following macros:
       INTMAX_C(value)
       UINTMAX_C(value)
These create maximum-width constants of the specified value.

Integer Format Conversion Functions

C99 adds a few specialized integer format conversion functions that allow you to convert to and from greatest-width integers. The header that supports these functions is <inttypes.h>, which includes <stdint.h>. The <inttypes.h> header defines one type: the structure imaxdiv_t, which holds the value returned by the imaxdiv( ) function. The integer conversion functions are shown here:
Function
Description
intmax_t imaxabs(intmax_t arg);
Returns the absolute value of arg.
imaxdiv_t imaxdiv(intmax_t numerator,
                               intmax_t denominator);
Returns an imaxdiv_t structure that contains the outcome of numerator/denominator. The quotient is the quot field and the remainder is in the rem field. Both quot and rem are of type intmax_t.
intmax_t strtoimax(const char * restrict start,
                                 char ** restrict end,
                                 int base);
The greatest-width integer version of strtol( ).
uintmax_t strtoumax(const char * restrict start,
                                    char ** restrict end,
                                    int base);
The greatest-width integer version of strtoul( ).
intmax_t wcstoimax(const char * restrict start,
                                   char ** restrict end,
                                   int base);
The greatest-width integer version of wcstol( ).
uintmax_t wcstoumax(const char * restrict start,
                                      char ** restrict end,
                                      int base);
The greatest-width integer version of wcstoul( ).
<inttypes.h> also defines many macros that can be used in calls to the printf( ) and scanf( ) family of functions to specify various integer conversions. The printf( ) macros begin with PRI and the scanf( ) macros begin with SCN. These prefixes are then followed by a conversion specifier, such as d or u, and then a type name, such as N, MAX, PTR, FASTN, or LEASTN, where N specifies the number of bits. Consult your compiler's documentation for a precise list of conversion macros 

Type-Generic Math Macros

C99 defines three versions for most mathematical functions: one for float, one for double, and one for long double parameters. For example, C99 defines these functions for the sine operation:
      double sin(double arg);
      float sinf(float arg);
      long double sinl(long double arg);
The operation of all three functions is the same, except for the data upon which they operate. In all cases, the double version is the original function defined by C89. The float and long double versions were added by C99. The float versions use the f suffix, and long double versions use the l suffix. (Different names are required because C does not support function overloading.) By providing three different functions, C99 enables you to call the one that most precisely fits the circumstances. As described earlier in this chapter, the complex math functions also provide three versions of each function, for the same reason.
As useful as the three versions of the math and complex functions are, they are not particularly convenient. First, you have to remember to specify the proper suffix for the data you are passing. This is both tedious and error-prone. Second, if you change the type of data being passed to one of these functions during project development, you will need to remember to change the suffix as well. Again, this is tedious and error-prone. To address these (and other) issues, C99 defines a set of type-generic macros that can be used in place of the math or complex functions. These macros automatically translate into the proper function based upon the type of the argument. The type-generic macros are defined in <tgmath.h>, which automatically includes <math.h> and <complex.h>.
The type-generic macros use the same names as the double version of the math or complex functions to which they translate. (These are also the same names defined by C89 and C++.) Thus, the type-generic macro for sin( ), sinf( ), and sinl( ) is sin( ). The type-generic macro of csin( ), csinf( ), and csinl( ) is also sin( ). As explained, the proper function is called based upon the argument. For example, given
long double ldbl;
float complex fcmplx;
Then,
cos(ldbl)
translates into
cosl(ldbl)
and
cos(fcmplx)
translates into
ccosf(fcmplx)
As these examples illustrate, the use of type-generic macros offers the C programmer convenience without loss of performance, precision, or portability.
NOTE: If you are programming in C++, the type-generic macros are not needed because C++ provides overloaded versions of the math and complex functions.

The <stdbool.h> Header

C99 adds the header <stdbool.h>, which supports the _Bool data type. Although it does not define any functions, it does define these four macros:
Macro
Expands To
_Bool
1
0
_ _bool_true_false_are_defined
1
The reason that C99 specified _Bool rather than bool as a keyword is that many existing C programs had already defined their own custom versions of bool. By defining the Boolean type as _Bool, C99 avoids breaking this preexisting code. The same reasoning goes for true and false. However, for new programs, it is best to include <stdbool.h> and then use the bool, true, and false macros. One advantage of doing so is that it allows you to create code that is compatible with C++.

Followers