# C Programming/Libraries

A *library* in C is a collection of header files, exposed for use by
other programs. The library therefore consists of an *interface*
expressed in a `.h` file (named the \"header\") and an *implementation*
expressed in a `.c` file. This `.c` file might be precompiled or
otherwise inaccessible, or it might be available to the programmer.
(Note: Libraries may call functions in other libraries such as the
Standard C or math libraries to do various tasks.)

The format of a library varies with the operating system and compiler
one is using. For example, in the Unix and Linux operating systems, a
library consists of one or more *object files*, which consist of object
code that is usually the output of a compiler (if the source language is
C or something similar) or an assembler (if the source language is
assembly language). These object files are then turned into a library in
the form of an archive by the *ar* archiver (a program that takes files
and stores them in a bigger file without regard to compression). The
filename for the library usually starts with \"lib\" and ends with
\".a\"; e.g. the *libc.a* file contains the Standard C library and the
\"libm.a\" the mathematics routines, which the linker would then link
in. Other operating systems such as Microsoft Windows use a \".lib\"
extension for libraries and an \".obj\" extension for object files. Some
programs in the Unix environment such as lex and yacc generate C code
that can be linked with the libl and liby libraries to create an
executable.

We\'re going to use as an example a library that contains one function:
a function to parse arguments from the command
line. Arguments on the command line could be by themselves:

`    -i`

have an optional argument that is
concatenated to the letter:

`    -ioptarg`

or have the argument in a separate argv-element:

`    -i optarg`

The library also has four declarations that it exports in addition to
the function: three integers and a pointer to the optional argument. If
the argument does not have an optional argument, the pointer to the
optional argument will be null.

In order to parse all these types of arguments, we have written the
following \"getopt.c\" file:

``` c
#include <stdio.h>              /* for fprintf() and EOF */
#include <string.h>             /* for strchr() */
#include "getopt.h"             /* consistency check */

/* variables */
int opterr = 1;                 /* getopt prints errors if this is on */
int optind = 1;                 /* token pointer */
int optopt;                     /* option character passed back to user */
char *optarg;                   /* flag argument (or value) */

/* function */
/* return option character, EOF if no more or ? if problem.
    The arguments to the function:
    argc, argv - the arguments to the main() function. An argument of "--"
    stops the processing.
    opts - a string containing the valid option characters.
    an option character followed by a colon (:) indicates that
    the option has a required argument.
*/
int
getopt (int argc, char **argv, char *opts)
{
    static int sp = 1;            /* character index into current token */
    register char *cp;            /* pointer into current token */
    
    if (sp == 1)
    {
        /* check for more flag-like tokens */
        if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
            return EOF;
        else if (strcmp (argv[optind], "--") == 0)
        {
            optind++;
            return EOF;
        }
    }
    
    optopt = argv[optind][sp];
    
    if (optopt == ':' || (cp = strchr (opts, optopt)) == NULL)
    {
        if (opterr)
            fprintf (stderr, "%s: invalid option -- '%c'\n", argv[0], optopt);
        
        /* if no characters left in this token, move to next token */
        if (argv[optind][++sp] == '\0')
        {
            optind++;
            sp = 1;
        }
        
        return '?';
    }
    
    if (*++cp == ':')
    {
        /* if a value is expected, get it */
        if (argv[optind][sp + 1] != '\0')
            /* flag value is rest of current token */
            optarg = argv[optind++] + (sp + 1);
        else if (++optind >= argc)
        {
            if (opterr)
                fprintf (stderr, "%s: option requires an argument -- '%c'\n",
                            argv[0], optopt);
            sp = 1;
            return '?';
        }
        else
                    /* flag value is next token */
                optarg = argv[optind++];
        sp = 1;
    }
    else
    {
        /* set up to look at next char in token, next time */
        if (argv[optind][++sp] == '\0')
        {
            /* no more in current token, so setup next token */
            sp = 1;
            optind++;
        }
        optarg = 0;
    }
    return optopt;
} 
/* END OF FILE */
```

The interface would be the following \"getopt.h\" file:

``` c
#ifndef GETOPT_H
    #define GETOPT_H

    /* exported variables */
    extern int opterr, optind, optopt;
    extern char *optarg;

    /* exported function */
    int getopt(int, char **, char *);
#endif

/* END OF FILE */
```

At a minimum, a programmer has the interface file to figure out how to
use a library, although, in general, the library programmer also wrote
documentation on how to use the library. In the above case, the
documentation should say that the provided arguments `**argv` and
`*opts` both shouldn\'t be null pointers (or why would you be using the
`getopt` function anyway?). Specifically, it typically states what each
parameter is for and what return values can be expected in which
conditions. Programmers that use a library, are normally not interested
in the implementation of the library \-- unless the implementation has a
bug, in which case he would want to complain somehow.

Both the implementation of the getopts library, and programs that use
the library should state `#include "getopt.h"`, in order to refer to the
corresponding interface. Now the library is \"linked\" to the program
\-- the one that contains the main() function. The program may refer to
dozens of interfaces.

In some cases, just placing `#include "getopt.h"` may appear correct but
will still fail to link properly. This indicates that the library is not
installed correctly, or there may be some additional configuration
required. You will have to check either the compiler\'s documentation or
library\'s documentation on how to resolve this issue.

## What to put in header files

As a general rule, headers should contain any declarations and macro
definitions (preprocessor `#define`s) to be \"seen\" by the other
modules in a program.

Possible declarations:

-   struct, union, and enum declarations
-   typedef declarations
-   external function declarations
-   global variable declarations

In the above `getopt.h` example file, one function (`getopt`) is
declared and four global variables (`optind`, `optopt`, `optarg`, and
`opterr`) are also declared. The variables are declared with the storage
class specifier `extern` in the header file because that keyword
specifies that the \"real\" variables are stored elsewhere (i.e. the
`getopt.c` file) and not within the header file.

The `#ifndef GETOPT_H/#define GETOPT_H` trick is colloquially called
`<b>`{=html}include guards`</b>`{=html}. This is used so that if the
`getopt.h` file were included more than once in a translation unit, the
unit would only see the contents once. Alternatively,
`#pragma once` in a header file can also be
used to achieve the same thing in some compilers (`#pragma` is an
unportable catchall).

## Linking Libraries Into Executables

Linking libraries into executables varies by operating system and
compiler/linker used. In Unix, directories of linked object files can be
specified with the `-L` option to the cc command and individual
libraries are specified with the `-l` (small ell) option. The `-lm`
option specifies that the libm math library should be linked in, for
example.

## References

-   C FAQ: \"I\'m wondering what to put in .c files and what to put in
    .h files. (What does \".h\" mean,
    anyway?)\"
-   PIClist thread: \"Global variables in projects with many C
    files.\"
-   \"How do I use extern to share variables between source files in
    C?\".

fr:Programmation C/Bibliothèque
standard
pl:C/Biblioteki
