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.
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.
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> */ /* ... */ #endifwhere
__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); /*...*/ #endifThe 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.
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.
<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.
<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
<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.
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.