[Previous] [Contents] [Next]

C Library Overview


Using Standard C Headers · C Library Conventions · Program Startup and Termination


All Standard C library entities are declared or defined in one or more standard headers. To make use of a library entity in a program, write an include directive that names the relevant standard header. The full set of Standard C headers constitutes a hosted implementation: <assert.h>, <ctype.h>, <errno.h>, <float.h>, <limits.h>, <locale.h>, <math.h>, <setjmp.h>, <signal.h>, <stdarg.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, and <time.h>

Still more headers (not described here), and changes to existing headers, are added with C99, a revision to the C Standard published in 1999.

A freestanding implementation of Standard C provides only a subset of these standard headers: <float.h>, <limits.h>, <stdarg.h>, and <stddef.h>. Each freestanding implementation defines:

Using Standard C Headers

You include the contents of a standard header by naming it in an include directive, as in:

#include <stdio.h>  /* include I/O facilities */

You can include the standard headers in any order, a standard header more than once, or two or more standard headers that define the same macro or the same type. Do not include a standard header within a declaration. Do not define macros that have the same names as keywords before you include a standard header.

A standard header never includes another standard header. A standard header declares or defines only the entities described for it in this document.

Every function in the library is declared in a standard header. The standard header can also provide a masking macro, with the same name as the function, that masks the function declaration and achieves the same effect. The macro typically expands to an expression that executes faster than a call to the function of the same name. The macro can, however, cause confusion when you are tracing or debugging the program. So you can use a standard header in two ways to declare or define a library function. To take advantage of any macro version, include the standard header so that each apparent call to the function can be replaced by a macro expansion.

For example:

#include <ctype.h>
char *skip_space(char *p)
    {
    while (isspace(*p))        can be a macro
        ++p;
    return (p);
    }

To ensure that the program calls the actual library function, include the standard header and remove any macro definition with an undef directive.

For example:

#include <ctype.h>
#undef isspace                 remove any macro definition
int f(char *p) {
    while (isspace(*p))        must be a function
        ++p;

You can use many functions in the library without including a standard header (although this practice is no longer permitted in C99 and is generally not recommended). If you do not need defined macros or types to declare and call the function, you can simply declare the function as it appears in this chapter. Again, you have two choices. You can declare the function explicitly.

For example:

    double sin(double x);      declared in <math.h>
    y = rho * sin(theta);

Or you can declare the function implicitly if it is a function returning int with a fixed number of arguments, as in:

    n = atoi(str);             declared in <stdlib.h>

If the function has a varying number of arguments, such as printf, you must declare it explicitly: Either include the standard header that declares it or write an explicit declaration.

Note also that you cannot define a macro or type definition without including its standard header because each of these typically varies among implementations.

C Library Conventions

A library macro that masks a function declaration expands to an expression that evaluates each of its arguments once (and only once). Arguments that have side effects evaluate the same way whether the expression executes the macro expansion or calls the function. Macros for the functions getc and putc are explicit exceptions to this rule. Their stream arguments can be evaluated more than once. Avoid argument expressions that have side effects with these macros.

A library function that alters a value stored in memory assumes that the function accesses no other objects that overlap the object whose stored value it alters. You cannot depend on consistent behavior from a library function that accesses and alters the same storage via different arguments. The function memmove is an explicit exception to this rule. Its arguments can point at objects that overlap.

An implementation has a set of reserved names that it can use for its own purposes. All the library names described in this document are, of course, reserved for the library. Don't define macros with the same names. Don't try to supply your own definition of a library function, unless this document explicitly says you can (only in C++). An unauthorized replacement may be successful on some implementations and not on others. Names that begin with two underscores (or contain two successive underscores, in C++), such as __STDIO, and names that begin with an underscore followed by an upper case letter, such as _Entry, can be used as macro names, whether or not a translation unit explicitly includes any standard headers. Names that begin with an underscore can be defined with external linkage. Avoid writing such names in a program that you wish to keep maximally portable.

Some library functions operate on C strings, or pointers to null-terminated strings. You designate a C string that can be altered by an argument expression that has type pointer to char (or type array of char, which converts to pointer to char in an argument expression). You designate a C string that cannot be altered by an argument expression that has type pointer to const char (or type const array of char). In any case, the value of the expression is the address of the first byte in an array object. The first successive element of the array that has a null character stored in it marks the end of the C string.

If an argument to a library function has a pointer type, then the value of the argument expression must be a valid address for an object of its type. This is true even if the library function has no need to access an object by using the pointer argument. An explicit exception is when the description of the library function spells out what happens when you use a null pointer.

Some examples are:

    strcpy(s1, 0)              is INVALID
    memcpy(s1, 0, 0)           is UNSAFE
    realloc(0, 50)             is the same as malloc(50)

Program Startup and Termination

The target environment controls the execution of the program (in contrast to the translator part of the implementation, which prepares the parts of the program for execution). The target environment passes control to the program at program startup by calling the function main that you define as part of the program. Program arguments are C strings that the target environment provides, such as text from the command line that you type to invoke the program. If the program does not need to access program arguments, you can define main as:

extern int main(void)
    { <body of main> }

If the program uses program arguments, you define main as:

extern int main(int argc, char **argv)
    { <body of main> }

You can omit either or both of extern int, since these are the default storage class and type for a function definition. For program arguments:

For example, if you invoke a program by typing:

echo hello

a target environment can call main with:

argv[0] is the name used to invoke the program. The target environment can replace this name with a null string (""). The program can alter the values stored in argc, in argv, and in the array objects whose addresses are stored in argv.

Before the target environment calls main, it stores the initial values you specify in all objects that have static duration. It also opens three standard streams, controlled by the text-stream objects designated by the macros:

If main returns to its caller, the target environment calls exit with the value returned from main as the status argument to exit. If the return statement that the program executes has no expression, the status argument is undefined. This is the case if the program executes the implied return statement at the end of the function definition.

You can also call exit directly from any expression within the program. In both cases, exit calls all functions registered with atexit in reverse order of registry and then begins program termination. At program termination, the target environment closes all open files, removes any temporary files that you created by calling tmpfile, and then returns control to the invoker, using the status argument value to determine the termination status to report for the program.

The program can terminate abnormally by calling abort, for example. Each implementation defines whether it closes files, whether it removes temporary files, and what termination status it reports when a program terminates abnormally.


See also the Table of Contents and the Index.

Copyright © 1989-2002 by P.J. Plauger and Jim Brodie. All rights reserved.

[Previous] [Contents] [Next]