C in C is best learned by connecting the rule to a small command-line program. Start with the smallest function, observe the output, and then add one realistic constraint so the concept becomes practical.
The key habit for this lesson is to watch pointer, array, or file buffer as it changes. That makes the topic easier to debug, easier to explain in interviews, and easier to use in real code without memorizing isolated syntax.
The C Standard Library is a collection of header files and functions defined by the C standard (C89/C99/C11). It provides ready-to-use implementations for I/O, string manipulation, math, memory management, date/time, and more - so you don't have to write them from scratch.
Provides common math functions. Compile with -lm flag: gcc program.c -lm
#include <stdio.h>
#include <math.h>
int main() {
printf("sqrt(16) = %.2f\n", sqrt(16)); // 4.00
printf("pow(2, 10) = %.0f\n", pow(2, 10)); // 1024
printf("fabs(-3.7) = %.2f\n", fabs(-3.7)); // 3.70
printf("ceil(4.1) = %.0f\n", ceil(4.1)); // 5
printf("floor(4.9) = %.0f\n", floor(4.9)); // 4
printf("round(4.5) = %.0f\n", round(4.5)); // 5
printf("log(M_E) = %.2f\n", log(M_E)); // 1.00 (natural log)
printf("log10(1000) = %.2f\n", log10(1000)); // 3.00
printf("sin(M_PI/2) = %.2f\n", sin(M_PI/2)); // 1.00
printf("cos(0) = %.2f\n", cos(0)); // 1.00
printf("fmod(10, 3) = %.2f\n", fmod(10, 3)); // 1.00 (float modulo)
return 0;
}
// Compile: gcc math_demo.c -lm -o math_demo
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Comparator for qsort (ascending)
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int main() {
// Random numbers
srand(time(NULL)); // seed with current time
printf("Random numbers (1-100):\n");
for (int i = 0; i < 5; i++) {
printf(" %d\n", rand() % 100 + 1);
}
// qsort - sort any array with a comparator
int arr[] = {64, 25, 12, 22, 11};
int n = 5;
qsort(arr, n, sizeof(int), compare);
printf("\nSorted: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n"); // 11 12 22 25 64
// bsearch - binary search (array must be sorted)
int key = 22;
int *found = (int*)bsearch(&key, arr, n, sizeof(int), compare);
if (found) printf("Found %d at index %ld\n", key, found - arr);
else printf("%d not found\n", key);
// abs, labs, llabs
printf("\nabs(-42) = %d\n", abs(-42));
printf("labs(-1M) = %ld\n", labs(-1000000L));
// exit codes
// exit(EXIT_SUCCESS); // 0 - normal termination
// exit(EXIT_FAILURE); // 1 - error termination
return 0;
}
#include <stdio.h>
#include <time.h>
int main() {
// Current time as timestamp
time_t now = time(NULL);
printf("Unix timestamp: %ld\n", (long)now);
// Convert to human-readable string
printf("Current time: %s", ctime(&now)); // includes \n
// Structured time
struct tm *t = localtime(&now);
printf("Year: %d\n", t->tm_year + 1900);
printf("Month: %d\n", t->tm_mon + 1);
printf("Day: %d\n", t->tm_mday);
printf("Hour: %d\n", t->tm_hour);
printf("Min: %d\n", t->tm_min);
// Format date string
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
printf("Formatted: %s\n", buffer);
// Benchmark: measure execution time
clock_t start = clock();
long sum = 0;
for (long i = 0; i < 100000000L; i++) sum += i;
clock_t end = clock();
double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("\nSum: %ld\n", sum);
printf("Time: %.4f seconds\n", elapsed);
return 0;
}
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main() {
char ch = 'A';
printf("isalpha('%c') = %d\n", ch, isalpha(ch)); // 1 (true)
printf("isdigit('5') = %d\n", isdigit('5')); // 1
printf("isspace(' ') = %d\n", isspace(' ')); // 1
printf("isupper('A') = %d\n", isupper('A')); // 1
printf("islower('a') = %d\n", islower('a')); // 1
printf("isalnum('3') = %d\n", isalnum('3')); // 1
printf("ispunct('!') = %d\n", ispunct('!')); // 1
printf("toupper('a') = %c\n", toupper('a')); // A
printf("tolower('Z') = %c\n", tolower('Z')); // z
// Convert string to uppercase
char str[] = "Hello, World!";
for (int i = 0; str[i]; i++) str[i] = toupper(str[i]);
printf("Uppercase: %s\n", str); // HELLO, WORLD!
return 0;
}
| Header | Key Functions |
|---|---|
| <stdio.h> | printf, scanf, fopen, fclose, fread, fwrite, fgets, fputs, sprintf, sscanf |
| <stdlib.h> | malloc, calloc, realloc, free, atoi, atof, rand, srand, qsort, bsearch, exit, abs |
| <string.h> | strlen, strcpy, strncpy, strcat, strcmp, strstr, strchr, memcpy, memset, memmove |
| <math.h> | sqrt, pow, fabs, ceil, floor, round, sin, cos, tan, log, log10, exp, fmod |
| <time.h> | time, clock, difftime, localtime, gmtime, mktime, strftime, ctime |
| <ctype.h> | isalpha, isdigit, isspace, isupper, islower, toupper, tolower, isalnum, ispunct |
| <errno.h> | errno, perror, strerror |
| <limits.h> | INT_MAX, INT_MIN, CHAR_MAX, LONG_MAX, UINT_MAX, LLONG_MAX |
| <stdbool.h> | bool, true, false (C99) |
| <stdint.h> | int8_t, int16_t, int32_t, int64_t, uint8_t, uint32_t, SIZE_MAX |
| <assert.h> | assert(condition) - aborts if condition is false |
| <signal.h> | signal, raise, SIGINT, SIGTERM, SIGSEGV |
Use C when the program needs a clear answer to a specific problem, not because the keyword looks familiar. In a real C task, first name the input, then name the transformation, then name the output. This small discipline shows whether the topic is being used correctly or only copied from an example.
A reliable practice flow is: create the smallest working function, add one normal case, add one edge case such as missing, repeated, empty, or boundary input, and then confirm the result with compiler warnings and printed output. If the result surprises you, reduce the code until the behavior is visible again.
The most common trap here is copying the syntax before understanding the behavior. Avoid it by writing one sentence before the code that explains why C is the right choice. After the code runs, verify the lesson by doing this: change one input and explain the changed output.
Copying the syntax before understanding the behavior.
Write the expected behavior first, then make the example prove it.
Practicing only the perfect input.
Also test missing, repeated, empty, or boundary input before considering the lesson complete.
Looking only at the final output.
Trace pointer, array, or file buffer through each important step.
Use it when the problem matches the behavior shown in the example and when the result can be verified through compiler warnings and printed output.
Start with a tiny case, then test missing, repeated, empty, or boundary input. The main warning sign is copying the syntax before understanding the behavior.
Trace pointer, array, or file buffer, predict the result, run the example, and compare your prediction with the actual output.
Explore 500+ free tutorials across 20+ languages and frameworks.