Skip to content

C Standard Library — Essential Functions in libc (stdlib, math, time, locale)

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about C Standard Library. We cover key concepts, practical examples, and best practices to help you master this topic.

The C standard library (libc) provides essential functions for memory management (malloc, calloc, realloc, free), algorithm utilities (qsort, bsearch, rand), integer math (abs, div), environment interaction (getenv, system, exit), and type conversion (atoi, strtol, atof).

What You Will Learn

  • Dynamic memory allocation with malloc, calloc, realloc, free
  • Sorting and searching with qsort and bsearch
  • Random number generation with rand and srand
  • String-to-number conversion with strtol, strtod
  • Environment variables with getenv and setenv
  • Process control with exit, atexit, system
  • Math library functions (sin, cos, sqrt, pow, fabs)
  • Time functions (time, clock, difftime, strftime)

Why It Matters

The standard library is the foundation of every C program. Knowing which functions exist and how to use them correctly prevents reinventing the wheel and avoids subtle bugs. Functions like strtol have well-defined error handling; functions like atoi do not. Durga Antivirus Pro uses qsort to sort scan results by severity, rand to generate random quarantine file names, strtol to parse configuration numbers, and clock_gettime for performance timing.

Real-World Use

A log analysis tool reads millions of log lines, parses timestamps and severity levels, sorts by timestamp (qsort), and finds specific entries (bsearch). If the tool uses atoi instead of strtol, it silently produces 0 for invalid input instead of reporting an error.

Learning Path

flowchart LR
  A[File I/O] --> B[Standard Library\nYou are here]
  B --> C[String Handling]
  style B fill:#f90,color:#fff

Sorting with qsort

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

int compare_int(const void *a, const void *b) {
    int ia = *(const int*)a;
    int ib = *(const int*)b;
    return (ia > ib) - (ia < ib);  // Returns -1, 0, or 1
}

int compare_string(const void *a, const void *b) {
    const char *sa = *(const char**)a;
    const char *sb = *(const char**)b;
    return strcmp(sa, sb);
}

int main() {
    int numbers[] = {42, 7, 15, 3, 99, 1, 8};
    size_t n = sizeof(numbers) / sizeof(numbers[0]);

    qsort(numbers, n, sizeof(int), compare_int);
    for (size_t i = 0; i < n; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    const char *fruits[] = {"banana", "apple", "date", "cherry", "elderberry"};
    size_t fn = sizeof(fruits) / sizeof(fruits[0]);
    qsort(fruits, fn, sizeof(char*), compare_string);
    for (size_t i = 0; i < fn; i++) {
        printf("%s ", fruits[i]);
    }
    printf("\n");

    return 0;
}

Binary Search with bsearch

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

int compare_int(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int main() {
    int sorted[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    size_t n = sizeof(sorted) / sizeof(sorted[0]);
    int target = 12;

    int *result = bsearch(&target, sorted, n, sizeof(int), compare_int);
    if (result) {
        int index = result - sorted;
        printf("Found %d at index %d\n", target, index);
    } else {
        printf("%d not found\n", target);
    }

    target = 7;
    result = bsearch(&target, sorted, n, sizeof(int), compare_int);
    if (result) {
        printf("Found %d at index %ld\n", target, result - sorted);
    } else {
        printf("%d not found\n", target);
    }

    return 0;
}

String to Number Conversion

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

int main() {
    const char *inputs[] = {"42", "   -17", "3.14", "abc", "123xyz", ""};
    size_t n = sizeof(inputs) / sizeof(inputs[0]);

    for (size_t i = 0; i < n; i++) {
        errno = 0;
        char *endptr;
        long val = strtol(inputs[i], &endptr, 10);

        if (errno == ERANGE) {
            printf("'%s': out of range\n", inputs[i]);
        } else if (endptr == inputs[i]) {
            printf("'%s': no digits found\n", inputs[i]);
        } else if (*endptr != '\0') {
            printf("'%s': parsed %ld, trailing: '%s'\n", inputs[i], val, endptr);
        } else {
            printf("'%s': %ld\n", inputs[i], val);
        }
    }

    // strtod for doubles
    const char *dstr = "3.14159265";
    char *dend;
    double dval = strtod(dstr, &dend);
    printf("Double: %f (trailing: '%s')\n", dval, dend);

    return 0;
}

Random Numbers

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

int main() {
    // Seed with current time
    srand(time(NULL));

    printf("Five random numbers:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", rand());
    }
    printf("\n");

    // Random in range [min, max]
    int min = 10, max = 20;
    printf("Random in [%d, %d]: ", min, max);
    for (int i = 0; i < 5; i++) {
        int r = min + rand() / (RAND_MAX / (max - min + 1) + 1);
        printf("%d ", r);
    }
    printf("\n");

    // Shuffle an array
    int arr[] = {1, 2, 3, 4, 5};
    size_t n = sizeof(arr) / sizeof(arr[0]);

    for (size_t i = n - 1; i > 0; i--) {
        size_t j = rand() % (i + 1);
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    printf("Shuffled: ");
    for (size_t i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    return 0;
}

Environment Variables and Process Control

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

void cleanup(void) {
    printf("Cleanup function called\n");
}

int main() {
    // Register cleanup on exit
    atexit(cleanup);

    // Read environment variables
    char *home = getenv("HOME");
    if (home) {
        printf("HOME: %s\n", home);
    }

    // Set environment variable
    setenv("MYAPP_CONFIG", "/etc/myapp.conf", 1);
    char *config = getenv("MYAPP_CONFIG");
    printf("Config: %s\n", config);

    // Execute a shell command
    printf("Running 'ls -la | head -3':\n");
    int ret = system("ls -la | head -3");
    printf("Command returned: %d\n", ret);

    return 0;
}

Math Library Functions

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

int main() {
    double x = 2.0;
    double y = 3.0;

    printf("sqrt(%.1f) = %.4f\n", x, sqrt(x));
    printf("pow(%.1f, %.1f) = %.4f\n", x, y, pow(x, y));
    printf("sin(%.1f) = %.4f\n", x, sin(x));
    printf("cos(%.1f) = %.4f\n", x, cos(x));
    printf("fabs(-%.1f) = %.1f\n", x, fabs(-x));
    printf("ceil(%.4f) = %.4f\n", 3.14, ceil(3.14));
    printf("floor(%.4f) = %.4f\n", 3.14, floor(3.14));
    printf("round(%.4f) = %.4f\n", 3.5, round(3.5));
    printf("fmod(%.1f, %.1f) = %.4f\n", 10.0, 3.0, fmod(10.0, 3.0));
    printf("exp(%.1f) = %.4f\n", 1.0, exp(1.0));
    printf("log(%.1f) = %.4f\n", x, log(x));
    printf("log10(%.1f) = %.4f\n", 100.0, log10(100.0));

    return 0;
}

Compile with -lm:

gcc -o math_demo math_demo.c -lm

Time Functions

#include <stdio.h>
#include <time.h>

int main() {
    // Current time
    time_t now = time(NULL);
    printf("Seconds since epoch: %ld\n", (long)now);

    // Convert to local time
    struct tm *local = localtime(&now);
    printf("Year: %d, Month: %d, Day: %d\n",
           local->tm_year + 1900, local->tm_mon + 1, local->tm_mday);
    printf("Hour: %d, Minute: %d, Second: %d\n",
           local->tm_hour, local->tm_min, local->tm_sec);
    printf("Day of week: %d, Day of year: %d\n",
           local->tm_wday, local->tm_yday);

    // Formatted date/time
    char buffer[64];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);
    printf("Formatted: %s\n", buffer);

    // Measure elapsed time
    clock_t start = clock();
    volatile double sum = 0;
    for (long i = 0; i < 100000000; i++) {
        sum += i * 0.000001;
    }
    clock_t end = clock();
    double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
    printf("Computation took %.4f seconds\n", elapsed);

    // difftime
    struct tm event = {0};
    event.tm_year = 2026 - 1900;
    event.tm_mon = 6 - 1;
    event.tm_mday = 28;
    time_t event_time = mktime(&event);
    double days = difftime(event_time, now) / 86400;
    printf("Days from event: %.0f\n", days);

    return 0;
}

Common Mistakes

  1. Using atoi/atof instead of strtol/strtod: atoi returns 0 on error with no way to distinguish from valid input "0". strtol provides full error detection via errno and the end pointer.

  2. Not seeding rand(): rand() without srand() produces the same sequence every run. Always call srand() once at program start with a varying seed (time, PID).

  3. Forgetting -lm for math functions: The math library is separate from libc. Link with -lm: gcc program.c -lm. Without it, you get undefined references.

  4. Misunderstanding qsort comparison function contract: The comparison must return negative, zero, or positive. Returning a - b for ints may overflow. Use the safe pattern: (a > b) - (a < b).

  5. Calling free on invalid pointers: Freeing a pointer twice, freeing stack memory, or freeing a pointer from a different allocator causes undefined behavior. Set pointers to NULL after freeing.

Practice Questions

  1. Why is strtol preferred over atoi for user input Parsing?
  2. What is the relationship between srand and rand?
  3. How does qsort's comparison function determine sort order?
  4. What does the endptr parameter of strtol indicate?
  5. Challenge: Write a program that reads a file of names (one per line), shuffles them randomly, sorts them alphabetically with qsort, splits them into teams of 5 using bsearch to locate team boundaries, and prints the teams. Use strtol to parse command-line arguments for input file, team size, and random seed.

Mini Project

Build a command-line statistics calculator:

  • Reads a file of numbers (one per line or comma-separated)
  • Uses strtod for parsing with error checking
  • Computes: count, sum, mean, median, min, max, standard deviation, percentiles (25th, 50th, 75th, 90th)
  • Uses qsort to sort for median/percentile calculations
  • Uses math functions (sqrt, pow, fabs) for standard deviation
  • Uses clock_gettime to measure and report computation time
  • Environment variable STATS_VERBOSE controls debug output
  • Options (via command-line args): --file, --verbose, --percentiles, --csv
  • Outputs formatted results with aligned columns

FAQ

What is the difference between malloc and calloc?

malloc allocates uninitialized memory. calloc allocates and zero-initializes it. calloc also takes two arguments (count, size) and checks for overflow.

What is RAND_MAX?

A constant defined in stdlib.h, typically 32767 or 2147483647. rand() returns a value between 0 and RAND_MAX inclusive. Do not use rand() % N for random ranges (modulo bias); use the division-based approach shown above.

How do I get a random double between 0 and 1?

Use (double)rand() / (double)RAND_MAX. For better randomness, use random() (BSD) or arc4random() or a PRNG library.

What is the difference between exit() and return from main?

exit() terminates immediately and runs atexit handlers. return from main() also terminates but may not run some cleanup (implementation-defined). Both return the exit code to the OS.

Why does my time() call return the same value every time?

time() returns seconds; calling it twice within the same second returns the same value. Use clock_gettime with CLOCK_REALTIME for nanosecond precision.

What is Next

Proceed to String Handling for deep coverage of string manipulation functions in string.h. Then explore Error Handling for robust error management patterns.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro

Home Browse C