Last updated: March 2025

C Header Files: Complete Guide to stdio.h, stdlib.h, string.h, math.h & More

By CoodeVerse Editorial Team ⏱ 11 min read

Every C program begins with #include directives that pull in the standard library functions you need. Knowing which header provides which function — and the gotchas attached to each — is one of the most practical skills in C. This guide covers every commonly-used C standard library header with a full function reference, a code example, and important notes that beginner tutorials usually skip.

Quick Lookup: Which Header Do I Need?

Use this table to find the right header for any function you want to use:

I want to…Function(s)Include
Print to the terminalprintf, puts, putchar<stdio.h>
Read from the terminalscanf, fgets, getchar<stdio.h>
Read/write filesfopen, fclose, fread, fwrite<stdio.h>
Allocate heap memorymalloc, calloc, realloc, free<stdlib.h>
Exit the programexit, abort, atexit<stdlib.h>
Generate random numbersrand, srand<stdlib.h>
Convert strings to numbersatoi, atof, strtol, strtod<stdlib.h>
Get string lengthstrlen<string.h>
Copy/compare stringsstrcpy, strncpy, strcmp, strncmp<string.h>
Find char/substringstrchr, strrchr, strstr<string.h>
Fill/copy memorymemset, memcpy, memmove<string.h>
Square root / powersqrt, pow, cbrt<math.h> + -lm
Trig functionssin, cos, tan, asin, acos, atan<math.h> + -lm
Round / ceiling / floorround, ceil, floor<math.h> + -lm
Get current timetime, clock, difftime<time.h>
Format date/time as stringstrftime, localtime, gmtime<time.h>
Test if char is digit/letterisdigit, isalpha, isspace<ctype.h>
Convert char casetoupper, tolower<ctype.h>
Use bool typebool, true, false<stdbool.h> (C99)
Fixed-width integersint32_t, uint8_t, int64_t<stdint.h> (C99)
<stdio.h> Standard Input/Output — the most commonly included header

stdio.h provides all functions for reading from and writing to the terminal, files, and strings. It is the first header included in virtually every C program.

FunctionPurposeKey note
printf(fmt, ...)Formatted output to stdoutReturns number of chars written
scanf(fmt, ...)Formatted input from stdinReturns items read — always check return value
fprintf(stream, fmt, ...)Formatted output to any FILEUse for stderr: fprintf(stderr, "error")
fscanf(stream, fmt, ...)Formatted input from any FILESame caveats as scanf
fopen(path, mode)Open a fileReturns NULL on failure — always check
fclose(fp)Close a file and flush bufferAlways call after fopen
fgets(buf, n, stream)Read a line (safer than gets)Never use gets() — it has no bounds
fputs(s, stream)Write a string to a FILEDoes not add a newline
fread(buf, size, n, fp)Binary read from fileReturns items read (0 on error/EOF)
fwrite(buf, size, n, fp)Binary write to fileReturns items written
feof(fp)Check end-of-fileTrue only after a read fails — not before
perror(msg)Print system error + descriptionUses errno — call immediately after failure
sprintf(buf, fmt, ...)Formatted print into a stringUnsafe if buf too small — prefer snprintf
snprintf(buf, n, fmt, ...)Formatted print into string (safe)Limits output to n-1 chars
stdio.h — file I/O exampleC
#include <stdio.h>

int main() {
    FILE *fp = fopen("data.txt", "w");
    if (!fp) { perror("fopen"); return 1; }

    fprintf(fp, "Line 1: score = %d\n", 95);
    fprintf(fp, "Line 2: name = %s\n", "Alice");
    fclose(fp);

    printf("File written successfully.\n");
    return 0;
}
Never use gets(). The function gets() has no way to limit how many characters it reads — any input longer than the buffer silently overwrites memory. It was removed from the C standard in C11. Always use fgets(buf, sizeof(buf), stdin) instead.
<stdlib.h> Standard Library — memory, conversion, random numbers, program control

stdlib.h is the second most commonly included header. It covers a wide range of utilities: dynamic memory allocation, string-to-number conversion, random number generation, sorting, and program exit.

FunctionPurposeKey note
malloc(size)Allocate bytes on heapReturns NULL on failure — check before use
calloc(n, size)Allocate and zero-initializeSafer than malloc for arrays
realloc(ptr, size)Resize heap allocationAssign to temp — if it fails, original is still valid
free(ptr)Release heap memoryEvery malloc must have exactly one free
exit(code)Exit program with codeFlushes stdio, calls atexit handlers
abort()Abnormal program terminationDoes NOT flush stdio or call atexit
atexit(func)Register cleanup functionCalled at normal exit in reverse order
rand()Pseudo-random int 0..RAND_MAXSeed with srand(time(NULL)) first
srand(seed)Seed random number generatorCall once at program start
atoi(s)String → intNo error detection — prefer strtol
atof(s)String → doubleNo error detection — prefer strtod
strtol(s, end, base)String → long (with error detection)Sets errno on overflow, *end = leftover
strtod(s, end)String → double (with error detection)Preferred over atof
qsort(arr, n, sz, cmp)Sort arrayProvide comparison function pointer
bsearch(key, arr, n, sz, cmp)Binary search sorted arrayReturns NULL if not found
abs(n) / labs(n)Absolute value int / longFor double use fabs() from math.h
stdlib.h — malloc and random numbersC
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    srand((unsigned)time(NULL));   // seed once

    int *arr = malloc(5 * sizeof(int));
    if (!arr) { perror("malloc"); return 1; }

    for (int i = 0; i < 5; i++) {
        arr[i] = rand() % 100;       // 0–99
        printf("%d ", arr[i]);
    }
    printf("\n");
    free(arr);
    return 0;
}
<string.h> String and memory operations

string.h provides functions for working with C strings (null-terminated char arrays) and raw memory blocks. C has no built-in string type, so these functions are essential.

FunctionPurposeSafety note
strlen(s)Length of string (not including \0)Does not count null terminator
strcpy(dst, src)Copy src into dstUnsafe if dst too small — use strncpy
strncpy(dst, src, n)Copy up to n charsDoes not guarantee null termination if src ≥ n
strcat(dst, src)Append src to dstUnsafe if dst too small — use strncat
strncat(dst, src, n)Append up to n charsAlways null-terminates
strcmp(s1, s2)Compare two stringsReturns 0 if equal, <0 or >0 otherwise
strncmp(s1, s2, n)Compare up to n charsSafer for partial comparison
strchr(s, c)Find first occurrence of char cReturns NULL if not found
strrchr(s, c)Find last occurrence of char cReturns NULL if not found
strstr(haystack, needle)Find substringReturns pointer to match or NULL
strtok(s, delim)Tokenize stringModifies the string — not thread-safe
memset(ptr, val, n)Fill n bytes with valUse to zero a struct: memset(&s, 0, sizeof(s))
memcpy(dst, src, n)Copy n bytesUndefined for overlapping regions — use memmove
memmove(dst, src, n)Copy n bytes (safe for overlap)Slower than memcpy but always correct
memcmp(s1, s2, n)Compare n bytesLike strcmp but for raw bytes
string.h — practical string operationsC
#include <stdio.h>
#include <string.h>

int main() {
    char s1[50] = "Hello";
    const char *s2 = "World";

    printf("Length of s1: %zu\n", strlen(s1));   // 5
    strncat(s1, ", ", sizeof(s1) - strlen(s1) - 1);
    strncat(s1, s2, sizeof(s1) - strlen(s1) - 1);
    printf("%s\n", s1);                          // Hello, World

    if (strcmp(s1, "Hello, World") == 0) {
        printf("Strings are equal\n");
    }

    char *pos = strstr(s1, "World");
    if (pos) printf("Found at index: %td\n", pos - s1);
    return 0;
}
<math.h> Mathematical functions — requires -lm flag

math.h provides floating-point mathematics. Remember: including this header is not enough — you must also link the math library with -lm at the end of your GCC command.

FunctionPurposeReturn type
sqrt(x)Square rootdouble
cbrt(x)Cube root (C99)double
pow(x, y)x raised to power ydouble
fabs(x)Absolute value of doubledouble
ceil(x)Round up to nearest integerdouble
floor(x)Round down to nearest integerdouble
round(x)Round to nearest (C99)double
fmod(x, y)Floating-point remainder x mod ydouble
log(x)Natural logarithm (base e)double
log2(x)Base-2 logarithm (C99)double
log10(x)Base-10 logarithmdouble
exp(x)e raised to power xdouble
sin/cos/tan(x)Trigonometric (radians)double
asin/acos/atan(x)Inverse trig (returns radians)double
atan2(y, x)Angle from (0,0) to (x,y)double
hypot(x, y)sqrt(x²+y²) without overflowdouble
Always add -lm when using math.h. The math library is deliberately not linked by default. Compile with: gcc program.c -o program -lm. The -lm must appear after the source files. Without it you get "undefined reference to 'sqrt'" even though you included math.h.
math.h — geometry calculationsC
#include <stdio.h>
#include <math.h>

#define PI  3.14159265358979

int main() {
    double r = 5.0;
    printf("Area of circle:   %.4f\n", PI * pow(r, 2));
    printf("Hypotenuse (3,4): %.4f\n", hypot(3.0, 4.0));
    printf("log2(1024):       %.1f\n",  log2(1024.0));
    return 0;
}
/* Compile: gcc program.c -o program -lm */
<time.h> Date, time, and elapsed time measurement

time.h provides functions for getting the current time, measuring elapsed time, and formatting dates and times as strings.

Function / TypePurpose
time(NULL)Current calendar time as time_t (seconds since Unix epoch)
clock()CPU time used by the program as clock_t
difftime(t2, t1)Difference between two time_t values in seconds
localtime(tp)Convert time_t to struct tm in local timezone
gmtime(tp)Convert time_t to struct tm in UTC
mktime(tm)Convert struct tm to time_t
strftime(buf, n, fmt, tm)Format struct tm as string (like sprintf for dates)
CLOCKS_PER_SECMacro: divide clock() result by this to get seconds
time.h — timing code executionC
#include <stdio.h>
#include <time.h>

int main() {
    /* Print current date/time */
    time_t now = time(NULL);
    struct tm *t = localtime(&now);
    char buf[64];
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", t);
    printf("Now: %s\n", buf);

    /* Time a computation */
    clock_t start = clock();
    long sum = 0;
    for (long i = 0; i < 100000000L; i++) sum += i;
    clock_t end = clock();

    printf("Elapsed: %.3f s\n",
           (double)(end - start) / CLOCKS_PER_SEC);
    return 0;
}
<ctype.h> Character classification and conversion

ctype.h provides functions for testing and converting individual characters. All functions take an int (the character value, or EOF) and return an int (non-zero = true, 0 = false for tests).

FunctionReturns true if…
isalpha(c)c is a letter (A–Z or a–z)
isdigit(c)c is a decimal digit (0–9)
isalnum(c)c is a letter or digit
isspace(c)c is whitespace (space, tab, newline, etc.)
isupper(c)c is an uppercase letter
islower(c)c is a lowercase letter
ispunct(c)c is a punctuation character
isprint(c)c is a printable character (including space)
iscntrl(c)c is a control character
toupper(c)Convert c to uppercase (returns int, cast to char)
tolower(c)Convert c to lowercase (returns int, cast to char)
ctype.h — count letters, digits, spaces in a stringC
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main() {
    const char *s = "Hello, World! 42";
    int letters = 0, digits = 0, spaces = 0;

    for (int i = 0; s[i]; i++) {
        if (isalpha((unsigned char)s[i])) letters++;
        else if (isdigit((unsigned char)s[i])) digits++;
        else if (isspace((unsigned char)s[i])) spaces++;
    }
    printf("Letters: %d  Digits: %d  Spaces: %d\n",
           letters, digits, spaces);
    return 0;
}
Cast to (unsigned char) before ctype functions. The ctype functions are defined for values 0–255 (unsigned char) and EOF (-1). Passing a char directly can produce undefined behavior on platforms where char is signed and the character has a value > 127 (e.g., accented letters). Always cast: isalpha((unsigned char)c).

C99 Additions: stdbool.h, stdint.h, inttypes.h

C99 introduced several new headers that fill important gaps in the original standard library. These are now universally available — always compile with -std=c99 or later to use them.

<stdbool.h> Boolean type — C99

Adds bool as a type alias for _Bool, and true (1) and false (0) as constants. Makes boolean intent explicit in code. In C23, these became built-in keywords — stdbool.h is no longer needed.

stdbool.hC99
#include <stdbool.h>

bool is_even(int n) { return n % 2 == 0; }

int main() {
    bool found = false;
    for (int i = 1; i <= 10; i++) {
        if (is_even(i)) { found = true; break; }
    }
    return found ? 0 : 1;
}
<stdint.h> Fixed-width integer types — C99

The size of int and long varies by platform (16, 32, or 64 bits). stdint.h provides types with guaranteed sizes — essential for embedded systems, network protocols, and any code that must be portable across hardware.

stdint.h — fixed-width integersC99
#include <stdio.h>
#include <stdint.h>

int main() {
    uint8_t  byte  = 255;     // always 8-bit unsigned
    int32_t  val   = -2147483648; // always 32-bit signed
    uint64_t large = 1000000000000ULL;

    printf("%u %d %llu\n", byte, val, large);
    return 0;
}

Common fixed-width types: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t. The uintN_t versions are unsigned.

Common Header Mistakes

Forgetting -lm after including math.h. Including <math.h> only gives the compiler the function declarations. The actual compiled math code lives in libm, which is not linked by default. Fix: gcc prog.c -o prog -lm (the flag goes at the end).
Using gets() from stdio.h. gets() was deprecated in C99 and removed in C11 because it cannot limit input length — it is a buffer overflow waiting to happen. Always use fgets(buf, sizeof(buf), stdin) instead.
Using atoi() instead of strtol(). atoi("abc") silently returns 0 with no indication of failure. strtol("abc", &end, 10) lets you detect that the conversion failed by checking whether end == input_str. In production code, always prefer strtol, strtoll, or strtod.
Including a header but not using any of its functions. Every unnecessary #include adds the contents of that header to your translation unit, slightly increasing compile time and potentially causing name conflicts. Include only what you use. With -Wunused-include-file (supported by some compilers), you can catch this automatically.

Frequently Asked Questions

Because including math.h only gives the compiler the function declaration. The actual implementation lives in libm, which is not linked by default. Add -lm at the end of your GCC command: gcc prog.c -o prog -lm.
atoi() converts a string to int but has no error detection — if the string is not a valid number, it silently returns 0. strtol(str, &end, base) is safer: if the conversion fails, end points to the first unconverted character (equal to str if nothing was converted), and it sets errno on overflow. Always prefer strtol in production code.
Without stdbool.h, C has no boolean type — you use int with the convention that 0 = false and non-zero = true. stdbool.h (C99) adds the bool type and true/false constants, making boolean intent explicit and the code more readable. In C23, bool, true, and false became built-in keywords — stdbool.h is then optional.
Use memcpy when source and destination regions do not overlap — it is faster. Use memmove when regions might overlap (e.g., shifting elements within the same array) — it handles overlapping correctly. Using memcpy on overlapping regions is undefined behavior.
stdint.h (C99) provides integer types with guaranteed sizes: int8_t, int16_t, int32_t, int64_t and their unsigned counterparts (uint8_t, etc.). Use them when you need an exact integer size — for network protocols (packets have defined byte widths), file formats, hardware registers, or any code that must produce identical results on 32-bit and 64-bit systems.

Continue learning C on CoodeVerse

CoodeVerse Editorial Team

The CoodeVerse editorial team consists of experienced software developers and educators specializing in C, Python, Java, and web development. All content is technically reviewed and updated regularly.