Previous Page
Next Page

15.1. Using the Standard Headers

You can add the contents of a standard header to a source file by inserting an #include directive, which must be placed outside all functions. You can include the standard headers as many times as you want, and in any order. However, before the #include directive for any header, your program must not define any macro with the same name as an identifier in that header. To make sure that your programs respect this condition, always include the required standard headers at the beginning of your source files, before any header files of your own.

15.1.1. Execution Environments

C programs run in one of two execution environments : hosted or freestanding. Most common programs run in a hosted environment; that is, under the control and with the support of an operating system. In a hosted environment , the full capabilities of the standard library are available. Furthermore, programs compiled for a hosted environment must define a function named main( ), which is the first function invoked on program start.

A program designed for a freestanding environment runs without the support of an operating system. In a freestanding environment , the name and type of the first function invoked when a program starts is determined by the given implementation. Programs for a freestanding environment cannot use complex floating-point types, and may be limited to the following headers:

float.h

iso646.h

limits.h

stdarg.h

stdbool.h

stddef.h

stdint.h


Specific implementations may also provide additional standard library resources.

15.1.2. Function and Macro Calls

All standard library functions have external linkage. You may use standard library functions without including the corresponding header by declaring them in your own code. However, if a standard function requires a type defined in the header, then you must include the header.

The standard library functions are not guaranteed to be reentrantthat is, two calls to a standard library function may not safely be in execution concurrently in one process. One reason for this rule is that several of the functions use and modify static variables, for example. As a result, you can't generally call standard library functions in signal handling routines. Signals are asynchronous, which means that a program may receive a signal at any time, even while it's executing a standard library function. If that happens, and the handler for that signal calls the same standard function, then the function must be reentrant. It is up to individual implementations to determine which functions are reentrant, or whether to provide a reentrant version of the whole standard library.

As the programmer, you are responsible for calling functions and function-like macros with valid arguments. Wrong arguments can cause severe runtime errors. Typical mistakes to avoid include the following:

  • Argument values outside the domain of the function, as in the following call:

        double x = -1.0, y = sqrt(x);

  • Pointer arguments that do not point to an object or a function, as in this function call with an uninitialized pointer argument:

        char *msg;  strcpy( msg, "error" );

  • Arguments whose type does not match that expected by a function with a variable number of arguments. In the following example, the conversion specifier %f calls for a float pointer argument, but &x is a pointer to double:

        double x;    scanf( "%f", &x );

  • Array address arguments that point to an array that isn't large enough to accommodate data written by the function. Example:

        char name[ ] = "Hi ";  strcat( name, "Alice" );

Macros in the standard library make full use of parentheses, so that you can use them in expressions in the same way as individual identifiers. Furthermore, each function-like macro in the standard library uses its arguments only once.[*] This means that you can call these macros in the same way as ordinary functions, even using expressions with side effects as arguments. Here is an example:

[*] The C99 standard contradicts itself on this point. In describing the use of library functions it says, "Any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once, fully protected by parentheses where necessary, so it is generally safe to use arbitrary expressions as arguments," but in its descriptions of the functions putc( ), putwc( ), getc( ), and getwc( ), the standard contains warnings like this one: "The putc function is equivalent to fputc, except that if it is implemented as a macro, it may evaluate stream more than once, so that argument should never be an expression with side effects." It is fair to hope that the warnings are obsolete, but perhaps safer just to avoid using arguments with side effectsor to use fputc( ) rather than putc( ), and so on.

    int c = 'A';
    while ( c <= 'Z' )  putchar( c++ );    // Output: 'ABC ... XYZ'

The functions in the standard library may be implemented both as macros and as functions. In such cases, the same header file contains both a function prototype and a macro definition for a given function name. As a result, each use of the function name after you include the header file invokes the macro. The following example calls the macro or function toupper( ) to convert a lowercase letter to uppercase:

    #include <ctype.h>
    /* ... */
      c = toupper(c);      // Invokes the macro toupper( ), if there is one.

However, if you specifically want to call a function and not a macro with the same name, you can use the #undef directive to cancel the macro definition:

    #include <ctype.h>
    #undef toupper         // Remove any macro definition with this name.
    /* ... */
      c = toupper(c)       // Calls the function toupper( ).

You can also call a function rather than a macro with the same name by setting the name in parentheses:

    #include <ctype.h>
    /* ... */
      c = (toupper)(c)     // Calls the function toupper( ).

Finally, you can omit the header containing the macro definition, and declare the function explicitly in your source file:

    extern int toupper(int);
    /* ... */
      c = toupper(c)       // Calls the function toupper( ).

15.1.3. Reserved Identifiers

When choosing identifiers to use in your programs, you must be aware that certain identifiers are reserved for the standard library. Reserved identifiers include the following:

  • All identifiers that begin with an underscore, followed by a second underscore or an uppercase letter, are always reserved. Thus you cannot use identifiers such as _ _x or _Max, even for local variables or labels.

  • All other identifiers that begin with an underscore are reserved as identifiers with file scope. Thus you cannot use an identifier such as _a_ as the name of a function or a global variable, although you can use it for a parameter, a local variable, or a label. The identifiers of structure or union members can also begin with an underscore, as long as the second character is not another underscore or an uppercase letter.

  • Identifiers declared with external linkage in the standard headers are reserved as identifiers with external linkage. Such identifiers include function names, as well as the names of global variables such as errno. Although you cannot declare these identifiers with external linkage as names for your own functions or objects, you may use them for other purposes. For example, in a source file that does not include string.h, you may define a static function named strcpy( ).

  • The identifiers of all macros defined in any header you include are reserved.

  • Identifiers declared with file scope in the standard headers are reserved within their respective name spaces. Once you include a header in a source file, you cannot use any identifier that is declared with file scope in that header for another purpose in the same name space (see "Identifier Name Spaces" in Chapter 1) or as a macro name.

Although some of the conditions listed here have "loopholes" that allow you to reuse identifiers in a certain name space or with static linkage, overloading identifiers can cause confusion, and it's generally safest to avoid the identifiers declared in the standard headers completely. In the following sections, we also list identifiers that have been reserved for future extensions of the C standard. The last three rules in the previous list apply to such reserved identifiers as well.


Previous Page
Next Page