3 Language  -< 3.9 Future  -< Rationale  -> 4.2 Diagnostics  -> 5 Appendices  Index

4  Library

4.1  Introduction

The Base Document for this section of the Standard was the 1984 /usr/group Standard. The /usr/group document contains definitions of some facilities which were specific to the UNIX Operating System and not relevant to other operating environments, such as pipes, ioctls, file access permissions and process control facilities.  Those definitions were dropped from the Standard.  Some other functions were excluded from the Standard because they were non-portable or were ill-defined. 

Other facilities not in the library Base Document but present in many UNIX implementations, such as the curses (terminal-independent screen handling) library were considered to be more complex and less essential than the facilities of the Base Document; these functions were not added to the Standard. 

4.1.1  Definitions of terms

The decimal-point character is the character used in the input or output of floating point numbers, and may be changed by setlocale. This is a library construct; the decimal point in numeric literals in C source text is always a period. 

4.1.2  Standard headers

Whereas in prior practice only certain library functions have been associated with header files, the Standard now mandates that all library functions have a header.  Several headers have therefore been added, and the contents of a few old ones have been changed. 

In many implementations the names of headers are the names of files in special directories.  This implementation technique is not required, however: the Standard makes no assumptions about the form that a file name may take on any system.  Headers may thus have a special status if an implementation so chooses.  Standard headers may even be built into a translator, provided that their contents do not become ``known''  until after they are explicitly included.  One purpose of permitting these header ``files'' to be ``built in''  to the translator is to allow an implementation of the C language as an interpreter in an un-hosted environment, where the only ``file'' support may be a network interface. 

The Committee decided to make library headers ``idempotent'' --- they should be includable any number of times, and includable in any order.  This requirement, which reflects widespread existing practice, may necessitate some protective wrappers within the headers, to avoid, for instance, redefinitions of typedefs.  To ensure that such protective wrapping can be made to work, and to ensure proper scoping of typedefs, headers may only be included outside of any declaration. 

Note to implementors: a common way of providing this ``protective wrapping'' is:

        #ifndef __ERRNO_H
        #define __ERRNO_H
        /* body of <errno.h> */
        /* ...               */
        #endif
where __ERRNO_H is an otherwise unused macro name.

Implementors often desire to provide implementations of C in addition to that prescribed by the Standard.  For instance, an implementation may want to provide system-specific I/O facilities in <stdio.h> A technique that allows the same header to be used in both the Standard-conforming and alternate implementations is to add the extra, non-Standard, declarations to the header as in this illustration:

        #ifdef __EXTENSIONS__
        typedef int file_no;
        extern int read(file_no _N, void * _Buffer, int _Nbytes);
        /*...*/
        #endif
The header is usable in an implementation of the Standard in the absence of a definition of __EXTENSIONS__, and the non-Standard implementation can provide the appropriate definitions to enable the extra declarations. 

4.1.2.1  Reserved identifiers

To give implementors maximum latitude in packing library functions into files, all external identifiers defined by the library are reserved (in a hosted environment).  This means, in effect, that no user supplied external names may match library names, not even if the user function has the same specification Thus, for instance, strtod may be defined in the same object module as printf, with no fear that link-time conflicts will occur.  Equally, strtod may call printf, or printf may call strtod, for whatever reason, with no fear that the wrong function will be called. 

Also reserved for the implementor are all external identifiers beginning with an underscore, and all other identifiers beginning with an underscore followed by a capital letter or an underscore.  This gives a space of names for writing the numerous behind-the-scenes non-external macros and functions a library needs to do its job properly. 

With these exceptions, the Standard assures the programmer that all other identifiers are available, with no fear of unexpected collisions when moving programs from one implementation to another.  [Footnote: See §3.1.2.1 for a discussion of some of the precautions an implementor should take to keep this promise.  Note also that any implementation-defined member names in structures defined in <time.h> and <locals.h> must begin with an underscore, rather than following the pattern of other names in those structures.]  Note, in particular, that part of the name space of internal identifiers beginning with underscore is available to the user --- translator implementors have not been the only ones to find use for ``hidden'' names.  C is such a portable language in many respects that this issue of ``name space pollution''  is currently one of the principal barriers to writing completely portable code.  Therefore the Standard assures that macro and typedef names are reserved only if the associated header is explicitly included. 

4.1.3  Errors  <errno.h>

<errno.h> is a header invented to encapsulate the error handling mechanism used by many of the library routines in math.h and strlib.h [Footnote: In earlier drafts of the Standard, errno and related macros were defined in <stddef.h> When the Committee decided that the other definitions in this header were of such general utility that they should be required even in freestanding environments, it created <errno.h>.] 

The error reporting machinery centered about the setting of errno is generally regarded with tolerance at best.  It requires a ``pathological coupling'' between library functions and makes use of a static writable memory cell, which interferes with the construction of shareable libraries.  Nevertheless, the Committee preferred to standardize this existing, however deficient, machinery rather than invent something more ambitious. 

The definition of errno as an lvalue macro grants implementors the license to expand it to something like *__errno_addr(), where the function returns a pointer to the (current) modifiable copy of errno.

4.1.4  Limits  <float.h> and <limits.h>

Both <float.h> and <limits.h> are inventions.  Included in these headers are various parameters of the execution environment which are potentially useful at compile time, and which are difficult or impossible to determine by other means. 

The availability of this information in headers provides a portable way of tuning a program to different environments.  Another possible method of determining some of this information is to evaluate arithmetic expressions in the preprocessing statements.  Requiring that preprocessing always yield the same results as run-time arithmetic, however, would cause problems for portable compilers (themselves written in C) or for cross compilers, which would then be required to implement the (possibly wildly different) arithmetic of the target machine on the host machine.  (See §3.4.) 

<float.h> makes available to programmers a set of useful quantities for numerical analysis. (See §2.2.4.2.)  This set of quantities has seen widespread use for such analysis, in C and in other languages, and was recommended by the numerical analysts on the Committee.  The set was chosen so as not to prejudice an implementation's selection of floating-point representation. 

Most of the limits in <float.h> are specified to be general double expressions rather than restricted constant expressions

4.1.5  Common definitions  <stddef.h>

<stddef.h> is a header invented to provide definitions of several types and macros used widely in conjunction with the library: ptrdiff_t (see §3.3.6), size_t (see §3.3.3.4), wchar_t (see §3.1.3.4), and NULL Including any header that references one of these macros will also define it, an exception to the usual library rule that each macro or function belongs to exactly one header. 

NULL can be defined as any null pointer constant Thus existing code can retain definitions of NULL as 0 or 0L, but an implementation may choose to define it as (void *)0; this latter form of definition is convenient on architectures where the pointer size(s) do(es) not equal the size of any integer type.  It has never been wise to use NULL in place of an arbitrary pointer as a function argument, however, since pointers to different types need not be the same size.  The library avoids this problem by providing special macros for the arguments to signal, the one library function that might see a null function pointer. 

The offsetof macro has been added to provide a portable means of determining the offset, in bytes, of a member within its structure.  This capability is useful in programs, such as are typical in data-base implementations, which declare a large number of different data structures: it is desirable to provide ``generic'' routines that work from descriptions of the structures, rather than from the structure declarations themselves.  [Footnote: Consider, for instance, a set of nodes (structures) which are to be dynamically allocated and garbage-collected, and which can contain pointers to other such nodes. A possible implementation is to have the first field in each node point to a descriptor for that node.  The descriptor includes a table of the offsets of fields which are pointers to other nodes.  A garbage-collector ``mark'' routine needs no further information about the content of the node (except, of course, where to put the mark).  New node types can be added to the program without requiring the mark routine to be rewritten or even recompiled.] 

In many implementations, offsetof could be defined as one of

        (size_t)&(((s_name*)0)->m_name)
or
        (size_t)(char *)&(((s_name*)0)->m_name)
or, where X is some predeclared address (or 0)  and A(Z) is defined as ((char*)&Z),
        (size_t)( A( (s_name*)X->m_name ) - A( X ))
It was not feasible, however, to mandate any single one of these forms as a construct guaranteed to be portable. 

Other implementations may choose to expand this macro as a call to a built-in function that interrogates the translator's symbol table. 

4.1.6  Use of library functions

To make usage more uniform for both implementor and programmer, the Standard requires that every library function (unless specifically noted otherwise) must be represented as an actual function, in case a program wishes to pass its address as a parameter to another function.  On the other hand, every library function is now a candidate for redefinition, in its associated header, as a macro, provided that the macro performs a ``safe'' evaluation of its arguments, i.e., it evaluates each of the arguments exactly once and parenthesizes them thoroughly, and provided that its top-level operator is such that the execution of the macro is not interleaved with other expressions.  Two exceptions are the macros getc and putc, which may evaluate their arguments in an unsafe manner.  (See §4.9.7.5.) 

If a program requires that a library facility be implemented as an actual function, not as a macro, then the macro name, if any, may be erased by using the #undef preprocessing directive (see §3.8.3). 

All library prototypes are specified in terms of the ``widened'' types: an argument formerly declared as char is now written as int This ensures that most library functions can be called with or without a prototype in scope (see §3.3.2.2), thus maintaining backwards compatibility with existing, pre-Standard, code.  Note, however, that since functions like printf and scanf use variable-length argument lists, they must be called in the scope of a prototype. 

The Standard contains an example showing how certain library functions may be ``built in''  in an implementation that remains conforming


3 Language  -< 3.9 Future  -< Rationale  -> 4.2 Diagnostics  -> 5 Appendices  Index