C Standard Library — Essential Functions in libc (stdlib, math, time, locale)
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
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.
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).
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.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).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
- Why is strtol preferred over atoi for user input Parsing?
- What is the relationship between srand and rand?
- How does qsort's comparison function determine sort order?
- What does the endptr parameter of strtol indicate?
- 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 Next
Proceed to String Handling for deep coverage of string manipulation functions in string.h. Then explore Error Handling for robust error management patterns.