Introduction to C

Perhaps you have heard of the language C. It is one of the most popular languages around. It's a simple language, and it's used mostly for systems programming. Let's take a tour of C.

Overview

Examples

Examples first, reference stuff later.

Hello, World

hello.c
 #include <stdio.h>

 int main() {
     printf("Hello, World\n");
     return 0;
 }

To compile this:

$ gcc hello.c

This produces a.exe on Windows systems and a.out on pretty much every other system.

Sometimes you might have to use one or more of the gcc options. Here are some common ones:

gcc -xc hello.c          (to tell gcc to compile C code, not C++)
gcc -std=c99 hello.c     (to use C99)
gcc -c hello.c           (to compile, but not link, the program)
gcc -S hello.c           (to translate to assembly language only)
gcc -o hello hello.c     (to make a nice output file name)
gcc -o hello.exe hello.c (if you have Windows)

Variables, Conditionals and Loops

This one is boring too, but it shows off for and if statements, and the fact that printf is useful:

triple.c
#include <stdio.h>

int main() {
    int a, b, c;

    printf("     A     B     C\n");
    printf("------------------\n");
    for (c = 1; c <= 100; c++) {
        for (b = 1; b <= 100; b++) {
            for (a = 1; a <= 100; a++) {
                if (a * a + b * b == c * c) {
                    printf("%6d%6d%6d\n", a, b, c);
                }
            }
        }
    }
    return 0;
}

This works in C90. In C99, you can declare a, b, and c in the for statements themselves.

Functions

pi.c
/*
 * A program that makes an approximation to pi by generating a million random
 * points in the unit square and computing the ratio of those inside the unit
 * circle to the total number in the square. That value should be pretty close
 * to Pi/4.  The program displays the approximation as wella as the actual
 * value to 10 digits.
 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

/*
 * Bad code, sort of. This program is simply approximating Pi using a million
 * probes, but a much better program would take a value as a command line
 * argument.  Oh well.  Okay for now.
 */
#define NUMBER_OF_PROBES 1000000

double squareOfDistanceToOrigin(double x, double y) {
    return x * x + y * y;
}

/*
 * Returns a random value in (-1..1)
 */
double randomValue() {
    return 2.0 * rand() / RAND_MAX - 1.0;
}

int main() {
    int i;
    int inside = 0;

    for (i = 0; i < NUMBER_OF_PROBES; i++) {
        double x = randomValue();
        double y = randomValue();
        if (squareOfDistanceToOrigin(x, y) < 1.0) {
            inside++;
        }
    }
    printf("Pi is about %12.10f (actual to 10 digits is %12.10f)\n",
            4.0 * ((double)inside / NUMBER_OF_PROBES), M_PI);

    return 0;
}

Arrays

C arrays are extraordinarily primitive. They do not not know how big they are, so you can read and write beyond the array bounds. For example:

int f() {
    int x;
    int a[4];
    int y;
    int z = 23;
    a[5] = 100;
    return z;
}

probably returns 100. And a[-1] is probably the same variable as x. You can also write things like a[x], x[a], a[3] and 3[a]. Trying to read or write a[234523132] will probably crash your program, though. Remember:

There are no array-index-out-of-bounds-exceptions in C because
  • C does not "remember" how big you created your array
  • C does not have exceptions

Here's a program with arrays

primes_to_1000.c
/*
 * A program that displays all the prime numbers up to and including 1000,
 * using the famous algorithm of Erathostenes.  This is a C99 program, not
 * a C90 program.
 *
 * The purpose of the program is only to illustrate arrays assuming one has
 * not yet seen pointers or command line arguments, so it isn't very good.
 */

#include <stdio.h>
#include <stdbool.h>

// To get primes up to and including 1000, the sieve has to have a slot at
// index 1000.  But indices must start at 0, so there have to be 1001 slots
// in the array.

#define SIZE 1001

// Fills the first n slots of array s with the given value.

void fillArray(bool s[], bool value, int n) {
    for (int i = 0; i < n; i++) {
        s[i] = value;
    }
}

// This function writes false in each slot of the array corresponding to a
// nonprime number.  First, we know 0 and 1 are not prime. Then for each
// value starting with 2, if the value is still thought to be prime, we
// write false in each slot corresponding to its multiples.

void checkOffComposites(bool s[], int n) {
    s[0] = false;
    s[1] = false;
    for (int i = 2; i * i < n; i++) {
        if (s[i]) {
            for (int j = i + i; j < n; j += i) {
                s[j] = false;
            }
        }
    }
}

// This function writes out all the values which correspond to positions in a
// vector containing the value true.  Each value is written to the standard
// output in a field of 8 characters.

void displayTrueIndices(bool s[], int n) {
    for (int i = 0; i < n; i++) {
        if (s[i]) {
            printf("%8d", i);
        }
    }
    printf("\n");
}

// main() just calls the worker functions.

int main() {
    bool sieve[SIZE];
    fillArray(sieve, true, SIZE);
    checkOffComposites(sieve, SIZE);
    displayTrueIndices(sieve, SIZE);
    return 0;
}

Pointers

A pointer is, more or less, an object through which you reference some other object.

int x = 5;
int* p = &x;
int* q = NULL;
int* r = malloc(sizeof(int));
int* s = malloc(100 * sizeof(int));

printf("%d %d %d", *p, *r, s[20]);
printf("%d", *q); /* CRASH */

free(r);
free(s);
/* But do not free p or q */

This picture captures the basic idea:

pointer.png

If the pointer
is called
Then the referent
is called
and the field
is called
p*p(*p).x or p->x
If the referent
is called
Then the pointer
is called
and the field
is called
p&pp.x

Pointers and arrays are closely related. The value of an array variable is a pointer to its first element (e.g. a == &a[0]), and

    e1[e2] is the same as *(e1 + e2)

For definitions pointers and arrays are different:

int *x;           /* is totally different from: */
int x[100];

int *a[n];        /* is totally different from: */
int a[n][100];

But for declarations, at least in parameter declarations, you can blur the distinction:

void f(int* a) { ... }
void g(int b[]) { ... }

An array of ints, or pointer to an int, can be passed to either.

Strings

Definitions from ISO/IEC 9899

So you can make a string with an array of characters with a zero at the end, or use string literals, which are sequences of (1) characters except \, ", and newlines, and (2) escapes (\a \b \f \n \r \t \v \' \" \? \\ \one-to-three-octaldigits \xhexdigits \ufour-hex-digits \Ueight-hex-digits). Let's just do examples:

strings.c
/*
 * A program that illustrates strings in C.  Designed for C99, but should run
 * fine in C90 with a lot of warnings.
 */

#include <stdio.h>
#include <string.h>
#include <wchar.h>

/* Simple strings from the basic character set */
char s1[] = {'d', 'o', 'g', (char)0};
char s2[] = {'d', 'o', 'g', '\0'};
char* s3 = "dog";
wchar_t* s4 = L"dog";

/* String with some non-ascii, but still "8-bit" characters */
char* s5 = "c\xe9ili";
char* s6 = "c\u00e9ili";
char* s7 = "c\U000000e9ili";
wchar_t* s8 = L"c\U000000e9ili";

/* Strings with characters with codepoints > 0xFF */
char* s9 = "k\u014dpa`a";
wchar_t* s10 = L"k\u014dpa`a";

void inspectString(char* s) {
    int i, n;
    printf("[%s] length=%d codepoints=[ ", s, strlen(s));
    for (i = 0, n = strlen(s)+1; i < n; i++) {
        printf("%02x ", (unsigned char)s[i]);
    }
    printf("]\n");
}

void inspectWideString(wchar_t* s) {
    int i, n;
    printf("[%ls] length=%d codepoints=[ ", s, wcslen(s));
    for (i = 0, n = (wcslen(s)+1)*sizeof(wchar_t); i < n; i++) {
        printf("%02x ", ((unsigned char*)s)[i]);
    }
    printf("]\n");
}

int main() {
    inspectString(s1);
    inspectString(s2);
    inspectString(s3);
    inspectString((char*)s4);
    inspectWideString(s4);
    inspectString(s5);
    inspectString(s6);
    inspectString(s7);
    inspectString((char*)s8);
    inspectWideString(s8);
    inspectString(s9);
    inspectString((char*)s10);
    inspectWideString(s10);
    return 0;
}

On a Windows XP box with an Intel Pentium 4, compiled with gcc 3.4.2, using a windows-1252 terminal, the output was:

> gcc strings.c && a
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[d] length=1 codepoints=[ 64 00 ]
[dog] length=3 codepoints=[ 64 00 6f 00 67 00 00 00 ]
[céili] length=5 codepoints=[ 63 e9 69 6c 69 00 ]
[c©ili] length=6 codepoints=[ 63 c3 a9 69 6c 69 00 ]
[c©ili] length=6 codepoints=[ 63 c3 a9 69 6c 69 00 ]
[c] length=1 codepoints=[ 63 00 ]
[céili] length=5 codepoints=[ 63 00 e9 00 69 00 6c 00 69 00 00 00 ]
[kÅ?pa`a] length=7 codepoints=[ 6b c5 8d 70 61 60 61 00 ]
[k] length=1 codepoints=[ 6b 00 ]
[kōpa`a] length=6 codepoints=[ 6b 00 4d 01 70 00 61 00 60 00 61 00 00 00 ]

On a Linux box with a Pentium M, compiled with gcc 4.1.2, using a UTF-8 terminal, the output was:

$ gcc strings.c && ./a.out
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[dog] length=3 codepoints=[ 64 6f 67 00 ]
[d] length=1 codepoints=[ 64 00 ]
[dog] length=3 codepoints=[ 64 00 00 00 6f 00 00 00 67 00 00 00 00 00 00 00 ]
length=5 codepoints=[ 63 e9 69 6c 69 00 ]
[céili] length=6 codepoints=[ 63 c3 a9 69 6c 69 00 ]
[céili] length=6 codepoints=[ 63 c3 a9 69 6c 69 00 ]
[c] length=1 codepoints=[ 63 00 ]
length=5 [63 00 00 00 e9 00 00 00 69 00 00 00 6c 00 00 00 69 00 00 00 00 00 00 00 ]
[kōpa`a] length=7 codepoints=[ 6b c5 8d 70 61 60 61 00 ]
[k] length=1 codepoints=[ 6b 00 ]
length=6 [6b 00 00 00 4d 01 00 00 70 00 00 00 61 00 00 00 60 00 00 00 61 00 00 00 00 00 00 00 ]

(The terminal dropped strings that could not be encoded in UTF-8.)

Signed and Unsigned Integers

C allows both! Be careful!

unsignedexample.c
/*
 * This is an example of three cases where mixing signed and unsigned values cause
 * trouble.
 */
#include <stdio.h>
#include <string.h>

void expect(int condition) {
    printf("%s\n", condition ? "Cool" : "Hey, WTF?");
}

/* FAIL! (Example from Bryant and O'Hallaron, page 77) */
int longerThan(char *s, char *t) {
    return strlen(s) - strlen(t) > 0;  /* FAIL */
}

int main() {
    int x = -1;
    int y = 1000000000;
    unsigned z = 3000000000;

    expect(x < y);
    expect(y < z);
    expect(x < z);
    expect(!longerThan("Jen", "Jennifer"));
}

Commandline Arguments

You can write the main() function with zero arguments, like we've been doing, or with two:

int main(int argc, char** argv) {
    /*
        argc is the number of command line arguments
        including the name of the program.

        argv is an array of strings containing the command
        line arguments.  argv[0] is the program name,
        argv[1] is the first argument (if present),
        argv[2] is the second, etc.
    */
}
Exercise: Write a program to print the commandline arguments, one per line. Try using things like * or *.c as arguments. Try using quotes, too.
Exercise: Write a program called compute that takes in exactly three arguments: an integer, an operator (one of "+", "=", "*", or "/") and another integer, then prints the result of the computation.

Files

A first example:

capitalizefile.c
/*
 * This is an inefficient program that takes two command line
 * arguments -- the first is the name of a file that should exist,
 * and the second the name of a file that should not exist ---
 * and creates the second file with the "capitalized" content of
 * the first.  If the second file already exists, it will be
 * overwritten.
 *
 * This program is slow because it uses fgetc and fputc.  Also,
 * it assumes the files are text files, so the file size of
 * the output file might differ from that of the input file.
 */

#include <stdio.h>
#include <ctype.h>

int main(int argc, char** argv) {
    if (argc != 3) {
        puts("Exactly two commandline arguments needed");
        return 1;
    } else {
        FILE* in = fopen(argv[1], "r");
        if (!in) {
            printf("File %s does not exist\n", argv[1]);
            return 2;
        }
        FILE* out = fopen(argv[2], "w");
        while (1) {
            int c = fgetc(in);
            if (c == EOF) break;
            fputc(toupper(c), out);
        }
        fclose(in);
        fclose(out);
        return 0;
    }
}

Most file operations are in <stdio.h>

Exercise: Run this program under Windows on a multi-line text file created on a Mac or Unix box, and note the difference in size between the two files.
Exercise: Clean up the capitalizer by using fread and fwrite.

Standard Input and Standard Output

There are two special filehandles that are always open and available to every C program: stdin and stdout. By default these are the current console, but they can be redirected, e.g.

$ myprogram < stuff.txt
$ myprogram > junk.txt
$ myprogram < stuff.txt > junk.txt

These functions automatically work on stdin and stdout:

NOTE: No one I know seems to have any idea how to make stdin and stdout behave as binary files. WTF????

Data Structures

This example shows both the use of arrays and pointers, and how to package things up so it looks like you have a class. Put the interface in a header file:

hashtable.h
/*
 * An abstract data type for sets-of-strings implemented as hashtables.
 */

/*
 * This module defines a type called HashTable.  The only way to
 * hide the representation of a type in C is to say that it is a
 * pointer to something, and define that something elsewhere.
 */

typedef struct H* HashTable;

/*
 * A hashtable must keep track of the hash function being used.
 * Since we are storing strings, the function must map strings to
 * ints.
 */

typedef int (*HashFunction)(char*);

/*
 * Hashtable operations.
 */

HashTable createHashTable(unsigned int capacity, HashFunction hash);
void addItem(HashTable table, char* item);
void removeItem(HashTable table, char* item);
int containsItem(HashTable table, char* item);
void destroyHashTable(HashTable table);

Then, the implementation

hashtable.c
/*
 * Implementation of the abstract data type for sets-of-strings implemented
 * as hashtables.
 */

#include <stdlib.h>
#include "hashtable.h"

/*
 * The hashtable will be implemented as an array of linked
 * lists of strings.  Here is the linked list part:
 */

struct Node;
typedef struct Node* Link;

struct Node {
    char* item;
    Link next;
};

/*
 * The table has the array of linked lists, its capacity (number
 * of cells in the array, and the hash function.  In the header file
 * we defined a HashTable as a pointer to a "struct H", so here
 * finally is the definition of struct H.
 */

struct H {
    Link* data;
    unsigned int capacity;
    HashFunction hash;
};

/*
 * Allocates a new node to hold the given initial values, and
 * returns a pointer to that node.  Returns NULL if the node
 * could not be allocated.
 */
Link newNode(char* item, Link next) {
    Link result = calloc(1, sizeof(struct Node));
    if (result == NULL) return NULL;
    result->item = item;
    result->next = next;
    return result;
}

/*
 * Creates a hashtable with the given capacity and hash function.
 * Returns a pointer to the newly created table, or NULL if the
 * table could not be created.
 */
HashTable createHashTable(unsigned int capacity, HashFunction hash) {
    HashTable table = (HashTable)calloc(1, sizeof(struct H));
    if (table == NULL) return NULL;
    table->data = (Link*)calloc(capacity, sizeof(Link));
    if (table->data == NULL) return NULL;
    table->capacity = capacity;
    table->hash = hash;
    return table;
}

/*
 * Adds the given item to the table, unless the item is already in
 * the table, in which case it does nothing.
 */
void addItem(HashTable table, char* item) {

    /* Which bucket does the item hash to? */
    int index = table->hash(item) % table->capacity;

    /* Search the linked list - if already there, bail! */
    Link p;
    for (p = table->data[index]; p != NULL; p = p->next) {
        if (strcmp(p->item, item) == 0) {
            return;
        }
    }

    /* Didn't find it in the list - add it! */
    table->data[index] = newNode(item, table->data[index]);
}

/*
 * Removes the given item from the table.  If the item isn't there,
 * this function does nothing.
 */
void removeItem(HashTable table, char* item) {

    /* Which bucket does the item hash to? */
    int index = table->hash(item) % table->capacity;

    /* Bail immediately if this bucket is empty */
    if (table->data[index] == NULL) return;

    /* Special case: if the item to be removed is the
     * FIRST one in the list, the array cell must be
     * modified.
     */
    if (strcmp(table->data[index]->item, item) == 0) {
        Link nodeToRemove = table->data[index];
        table->data[index] = table->data[index]->next;
        free(nodeToRemove);
        return;
    }

    /* Check all the nodes besides the first one in the list;
     * remove immediately if found.
     */
    Link p;
    for (p = table->data[index]; p->next != NULL; p = p->next) {
        if (strcmp(p->next->item, item) == 0) {
            Link nodeToRemove = p->next;
            p->next = p->next->next;
            free(nodeToRemove);
            return;
        }
    }
}

/*
 * Returns 1 (true) if item is in table, otherwise returns 0 (false).
 */
int containsItem(HashTable table, char* item) {

    /* Which bucket does the item hash to? */
    int index = table->hash(item) % table->capacity;

    /* Search the linked list */
    Link p;
    for (p = table->data[index]; p != NULL; p = p->next) {
        if (strcmp(p->item, item) == 0) {
            return 1;
        }
    }

    /* Didn't find it in the list */
    return 0;
}

/*
 * Cleans up any memory allocated when we created the hashtable.
 */
void destroyHashTable(HashTable table) {
    /* First free the linked list nodes */
    int i;
    for (i = 0; i < table->capacity; i++) {
        while (table->data[i] != 0) {
            Link nodeToRemove = table->data[i];
            table->data[i] = table->data[i]->next;
            free(nodeToRemove);
        }
    }

    /* Then free the table struct. */
    free(table->data);

    /* Free the table itself, because createHashTable allocated space */
    free(table);
}

Unit Testing

A unit test for the hashtable module above

hashtabletest.c
/*
 * Unit test for the hashtable abstract data type.  It isn't very complete.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "hashtable.h"

int stupidHash(char* s) {
    return (strlen(s) == 0) ? 20 : s[0] * s[strlen(s) - 1];
}

int main() {
    HashTable table = createHashTable(6, stupidHash);

    addItem(table, "dog");
    addItem(table, "cat");
    addItem(table, "ear");
    addItem(table, "egg");
    addItem(table, "bag");
    addItem(table, "zoo");
    addItem(table, "pig");
    addItem(table, "cat");
    addItem(table, "gag");
    addItem(table, "bat");

    assert(containsItem(table, "pig"));
    assert(containsItem(table, "zoo"));
    assert(containsItem(table, "cat"));
    assert(containsItem(table, "ear"));
    assert(containsItem(table, "bat"));
    assert(containsItem(table, "pig"));
    assert(!containsItem(table, "hog"));
    assert(!containsItem(table, "fit"));
    assert(!containsItem(table, "git"));

    removeItem(table, "zoo");
    removeItem(table, "fig");
    assert(containsItem(table, "egg"));
    assert(!containsItem(table, "zoo"));
    assert(!containsItem(table, "fig"));
    assert(!containsItem(table, "git"));

    addItem(table, "zoo");
    assert(containsItem(table, "zoo"));

    destroyHashTable(table);

    puts("All tests passed\n");
    return 0;
}

If you don't like the declared types...

This program shows off the kind of thing C is good for. It puts integers into 32-bit memory locations that interprets the data in those locations as floats and writes them (Gaaack! No, wait, it's okay, this is what C is for!).

numbers.c
/*
 * This program takes in two integer arguments (call them x and y) and writes
 * all the values in between them (inclusive) in hex, decimal, and as floating
 * point values.  Yikes.
 */

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    int low;
    int high;
    int x;

    if (argc != 3) {
        printf("You need exactly two integer arguments");
        return -1;
    }

    low = atoi(argv[1]);
    high = atoi(argv[2]);
    x = low;
    do {
        printf("%08X  %10d  %#16.7e\n", x, x, *((float*)&x));
    } while (x++ != high);

    return 0;
}

Something Cool

This is a cool self-printing program written in K&R C — it is not legal in modern C.

self.c
main(){char*c="main(){char*c=%c%s%c;printf(c,34,c,34);}";printf(c,34,c,34);}
Exercise: Write the smallest self-printing C99 program you can.

Machine Code in a String

Here's a fun one. It executes x86 machine code directly. Of course it will only work on an x86. C does not promise portability.

onehundred.c
/*
 * Illustration of executing machine code as a C string.  Works on an
 * IA-32 processor.
 */

#include <stdio.h>

int (*f)() = "\xb0\x64\x0f\xb6\xc0\xc3";

int main() {
    printf("%d\n", f());
    return 0;
}
Exercise: Write the equivalent program for a SPARC or PowerPC processor.

Some Reference Material

Here is a very sparse collection of C99 reference material.

Reserved Words

Reserved words are those that cannot be used as identifiers.

auto         break         case        char        const
continue     default       do          double      else
enum         extern        float       for         goto
if           inline        int         long        register
restrict     return        short       signed      sizeof
static       struct        switch      typedef     union
unsigned     void          volatile    while       _Bool
_Complex     _Imaginary

Types

C has 21 built-in types, one pseudo type, and five mechanisms to create user defined types.

Declarations

In C you declare entities with declarators, which are pretty hideous in hindsight, though some people love them.

Examples:

int x, *y, z[5], *r[7], (*s)[7], ***q, a(int), *b(int), (*c)(int), **d[5][9];

These mean

Statements

Operators

Here are the C operators, presented from highest to lowest precedence.

Operator(s)AssociativityComments
[], (), ., -> L subscript, call, structure field access, structure field access through pointer
!, ~, +, -, &, *, ++, --, sizeof
R logical-not, bitwise-not, unary-plus, unary-negation, address-of, dereference, increment, decrement, size
(type) L type conversion
*, /, % L multiply, divide, modulo
+, - L add, subtract
<<, >> L bitwise shifts
<, <=, >, >= L less-than, less-than-or-equal, greater-than, greater-than-or-equal
==, != L equal-to, not-equal-to
& L bitwise-and
^ L bitwise-xor
| L bitwise-or
&& L logical-short-circuit-and
|| L logical-short-circuit-or
?: R conditional
=
*=, /=, %=, +=, -=
<<=, >>=,
&=, ^=, |=
R assignment
, L comma

Standard Library

The standard library has tons of global types and functions grouped into 24 library modules. Beware that C has no real classes and in fact has no namespace mechanism whatsoever. So what! Live with it. If you need a million line program use a different language.

The University of Tasmania hosts a pretty decent one-page online reference for the library as of C90, which gives descriptions of the functions, macros, types and variables. Eric Huss has a longer, more detailed library reference, also for C90. If you like the JavaDoc format, you'll love the C Library Reference at CPlusPlus.com. For a full C99 reference, see the official standard. Here is a brief outline of what's in the C99 library. It lists all of the modules but only some of the contents.

ModuleDescriptionSample Contents
<assert.h>Diagnostics assert
<complex.h>Complex numbers complex, _Complex_I, I, CX_LIMITED_RANGE, c[a]cos[h][f|l], c[a]sin[h][f|l], c[a]tan[h][f|l], cexp[f|l], clog[f|l], cabs[f|l], cpow[f|l], csqrt[f|l], carg[f|l], cimag[f|l], conj[f|l], cproj[f|l], creal[f|l]
<ctype.h>Character handling islanum, isalpha, isblank, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper
<errno.h>Errors errno, EDOM, EILSEQ, ERANGE
<fenv.h>Floating-point environment fenv_t, fexcept_t, FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW, FE_UNDERFLOW, FE_ALL_EXCEPT, FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DFL_ENV, FENV_ACCESS, fclearexcept, fegetexceptflag, feraiseexcept, fesetexceptflag, fetestexcept, fegetround, fesetround, fegetenv, feholdexcept, fesetenv, feupdateenv
<float.h>Characteristics of floating types FLT_ROUNDS, FLT_EVAL_METHOD, FLT_RADIX, (FLT|[L]DBL)_DIG, DECIMAL_DIG, (FLT|[L]DBL)_MAINT_DIG, (FLT|[L]DBL)_MIN[_10]_EXP, (FLT|[L]DBL)_MAX[_10]_EXP, (FLT|[L]DBL)_MIN, (FLT|[L]DBL)_MAX, (FLT|[L]DBL)_EPSILON
<inttypes.h>Format conversion of integer types (see the C99 standard for these)
<iso646.h>Alternative spellings and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq
<limits.h>Sizes of integer types CHAR_BIT, [S]CHAR_MIN, [S|U]CHAR_MAX, MB_LEN_MAX, SHRT_MIN, [U]SHRT_MAX, INT_MIN, [U]INT_MAX, LONG_MIN, [U]LONG_MAX, LLONG_MIN, [U]LLONG_MAX
<locale.h>Localization struct lconv, NULL, LC_ALL, LC_NUMERIC, LC_MONETARY, LC_COLLATE, LC_CTYPE, LC_TIME, setlocale, localeconv
<math.h>Mathematics float_t, double_t, HUGE_VAL[F|L], INFINITY, NAN, FP_INFINITE, FP_NAN, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, FP_FAST_FMA[F|L], FP_ILOGB[0|NAN], MATH_ERRNO, MATH_ERREXCEPT, math_errhandling, FP_CONTRACT, fpclassify, isfinite, isinf, isnan, isnormal, signbit, [a]sin[h][f|l], [a]cos[h][f|l], [a]tan[h][f|l], atan2[f|l], exp[f|l], exp2[f|l], expm1[f|l], frexp[f|l], ilogb[f|l], ldexp[f|l], log[f|l], log10[f|l], log1p[f|l], log2[f|l], logb[f|l], modf[f|l], scalb[l]n[f|l], cbrt[f|l], fabs[f|l], hypot[f|l], pow[f|l], sqrt[f|l], erf[c][f|l], (l|t)gamma[f|l], ceil[f|l], floor[f|l], nearbyint[f|l], [l][l]rint[f|l], [l][l]round[f|l], trunc[f|l], fmod[f|l], remainder[f|l]. remquo[f|l], copysign[f|l], nan[f|l], nextafter[f|l], nexttoward[f|l], fdim[f|l], fmin[f|l], fmax[f|l], fma[f|l], isgreater, isgreaterequal, isless, islessequal, islessgreater, isunordered
<setjmp.h>Nonlocal jumps jmp_buf, setjmp, longjmp
<signal.h>Signal handling sig_atomic_t, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIG_DFL, SIG_ERR, SIG_IGN, signal, raise
<stdarg.h>Variable arguments va_list, va_start, va_arg, va_end, va_copy
<stdbool.h>Boolean type and values bool, true, false, __bool_true_false_are_defined
<stddef.h>Common definitions NULL, offsetof, ptrdiff_t, size_t, wchar_t
<stdint.h>Integer types intN_t, uintN_t, int_leastN_t, uint_leastN_t, int_fastN_t, uint_fastN_t, intptr_t, uintptr_t, intmax_t, uintmax_t, INTN_MIN, INTN_MAX, UINTN_MAX, INT_LEASTN_MIN, INT_LEASTN_MAX, UINT_LEASTN_MAX, INT_FASTN_MIN, INT_FASTN_MAX, UINT_FASTN_MAX, INTPTR_MIN, INTPTR_MAX, UINTPTR_MAX, INTMAX_MIN INTMAX_MAX, UINTMAX_MAX, PTRDIFF_MIN, PTRDIFF_MAX, SIG_ATOMIC_MIN, SIG_ATOMIC_MAX, SIZE_MAX, WCHAR_MIN, WCHAR_MAX, WINT_MIN, WINT_MAX, INTN_C, UINTN_C, INTMAX_C, UINTMAX_C
<stdio.h>Input/output FILE, fpos_t, size_t, BUFSIZ, EOF, FILENAME_MAX, FOPEN_MAX, L_tmpnam, NULL, SEEK_CUR, SEEK_END, SEEK_SET, TMP_MAX, _IO(F|L|N)BF, stdin, stdout, stderr, remove, rename, tmpfile, tmpnam, fclose, fflush, fopen, freopen, set[v]buf, [v][f|s|sn]printf [v][f|s]scanf, [f]getc, [f]gets, [f]putc, [f]puts, getchar, putchar, ungetc, fread, fwrite, fseek, ftell, rewind, fgetpos, fsetpos, clearerr, feof, ferror, perror
<stdlib.h>General utilities EXIT_FAILURE, EXIT_SUCCESS, RAND_MAX, NULL, MB_CUR_MAX, div_t, ldiv_t, lldiv_t, wchar_t, size_t, ato(i|f|l|ll), strto(f|d|ld|l|ll|ul|ull), rand, srand, calloc, malloc, realloc, free, abort, exit, atexit, _Exit, system, getenv, bsearch, qsort, [l][l]abs, [l][l]div, mblen, mbtowc, wctomb, mbstowcs, wcstombs
<string.h>String handling NULL, size_t, str[n]cpy, str[n]cat, str[n]cmp, strcoll, str[r]chr, strspn, strcspn, strpbrk, strstr, strlen, strerror, strtok, strxfrm, memcpy, memmove, memcmp, memchr, memset
<tgmath.h>Type-generic math acos, asin, atan, acosh, asinh, atanh, cos, sin, tan, cosh, sinh, tanh, exp, log, pow, sqrt, fabs, atan2, cbrt, ceil, copysign, erf, erfc, exp2, expm1, fdim, floor, fma, fmax, fmin, fmod, frexp, hypot, ilogb, ldexp, lgamma, llrint, llround, log10, log1p, log2, logb, lrint, lround, nearbyint, nextafter, nexttoward, remainder, remquo, rint, round, scalbn, scalbln, tgamma, trunc, carg, cimag, conj, cproj, creal
<time.h>Date and time CLOCKS_PER_SEC, NULL, size_t, clock_t, time_t, struct tm, clock, time, difftime, mktime, asctime, ctime, gmtime, localtime, strftime
<wchar.h>Wide character utilities wchar_t, size_t, mbstate_t, wint_t, struct_tm, NULL, WCHAR_MAX, WCHAR_MIN, WEOF, [f|s|vf|vs|v]wprintf, [f|s|vf|vs|v]wscanf, fgetw(c|s), fputw(c|s), fwide, getwc[har], putwc[har], ungetwc, wcsto(f|d|ld|l|ul|ll|ull), wcs[n]cpy, wmemcpy, wmemmove, wcs[n]cat, wcs[n]cmp, wcscoll, wcsxfrm, wmemcmp, wcschr, wcscspn, wcspbrk, wcsrchr, wcsspn, wcsstr, wcstok, wmemchr, wcslen, wmemset, wcsftime, btowc, wctob, mbsinit, mbrlen, mbrtowc, wcrtomb, mbsrtowcs, wcsrtombs
<wctype.h>Wide character classification and mapping utilities wint_t, wctrans_t, wctype_t, WEOF, iswalnum, iswalpha, iswblank, iswcntrl, iswdigit, iswgraph, iswlower, iswprint, iswpunct, iswspace, iswupper, iswxdigit, iswctype, wctype, towlower, towupper, towctrans, wctrans