C Programming Language Guide — Pointers, Memory, and Systems Programming
C is a procedural systems programming language that gives you direct control over memory through pointers and manual allocation, forming the foundation of operating systems, embedded firmware, and high-performance computing.
What You’ll Learn
- Pointers and pointer arithmetic
- Manual memory management with
mallocandfree - Structs for custom data types
- File I/O operations
- Building projects with Make and gcc
Why It Matters
C is the language that built everything — Linux, Windows, Python, Git, and virtually every operating system kernel. Durga Antivirus Pro uses C in its core scanning engine for maximum performance and low-level file system access. Understanding C gives you insight into how computers actually work, making you a better programmer in every other language. Embedded systems, IoT devices, and game engines all rely on C.
Learning Path
flowchart LR
A[C Basics<br/>You are here] --> B[Pointers & Arrays]
B --> C[Memory Management]
C --> D[Structs & File I/O]
D --> E[Build an Embedded App]
Your First C Program
C programs start at the main function. The #include directive brings in header files with function declarations.
#include <stdio.h>
int main() {
printf("Hello, C!\n");
return 0;
}gcc hello.c -o hello
./hello
# Hello, C!Pointers
A pointer stores a memory address. The * operator dereferences it; & gets an address.
#include <stdio.h>
int main() {
int x = 42;
int *ptr = &x; // ptr holds the address of x
printf("Value of x: %d\n", x); // 42
printf("Address of x: %p\n", &x); // 0x7ff...
printf("Value at ptr: %d\n", *ptr); // 42
*ptr = 100; // change x through the pointer
printf("New x: %d\n", x); // 100
return 0;
}Pointer Arithmetic
Adding to a pointer moves it by multiples of the type’s size.
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // points to arr[0]
printf("%d ", *ptr); // 10
printf("%d ", *(ptr + 1)); // 20
printf("%d ", *(ptr + 2)); // 30
printf("%d ", *(ptr + 3)); // 40
printf("%d\n", *(ptr + 4)); // 50
// Equivalent array notation:
for (int i = 0; i < 5; i++) {
printf("%d ", *(arr + i));
}
printf("\n");
// 10 20 30 40 50
return 0;
}Memory Management with malloc and free
C requires manual memory allocation. malloc allocates memory on the heap; free releases it.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr;
int n = 5;
// Allocate memory for 5 integers
arr = (int *)malloc(n * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
// Use the memory
for (int i = 0; i < n; i++) {
arr[i] = i * i;
}
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 0 1 4 9 16
// Free the memory
free(arr);
arr = NULL; // prevent dangling pointer
return 0;
}Structs
Structs group related variables together.
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int age;
float gpa;
};
int main() {
struct Student s1;
strcpy(s1.name, "Alice");
s1.age = 20;
s1.gpa = 3.8;
printf("Name: %s\n", s1.name); // Name: Alice
printf("Age: %d\n", s1.age); // Age: 20
printf("GPA: %.1f\n", s1.gpa); // GPA: 3.8
return 0;
}File I/O
C reads and writes files through file pointers.
#include <stdio.h>
int main() {
// Write to a file
FILE *f = fopen("data.txt", "w");
if (f == NULL) {
printf("Error opening file\n");
return 1;
}
fprintf(f, "Line 1: Hello\n");
fprintf(f, "Line 2: World\n");
fclose(f);
// Read from a file
f = fopen("data.txt", "r");
char buffer[100];
while (fgets(buffer, sizeof(buffer), f) != NULL) {
printf("%s", buffer);
}
fclose(f);
return 0;
}Output:
Line 1: Hello
Line 2: WorldMake and GCC
A Makefile automates compilation. Here’s a minimal example:
CC = gcc
CFLAGS = -Wall -Wextra -std=c99
all: program
program: main.c utils.c
$(CC) $(CFLAGS) -o program main.c utils.c
clean:
rm -f program
make
# gcc -Wall -Wextra -std=c99 -o program main.c utils.cCommon Mistakes
1. Off-by-one errors in arrays
int arr[5];
arr[5] = 10; // buffer overflow — accessing memory beyond the array
Array indexes go from 0 to n-1. Accessing arr[n] is undefined behavior.
2. Forgetting to free memory (memory leaks)
Every malloc must have a matching free. Long-running programs that leak memory will eventually exhaust available RAM.
3. Using uninitialized pointers
int *ptr;
*ptr = 5; // crash — ptr points to garbage
Always initialize pointers to NULL or a valid address.
4. Dangling pointers after free
int *ptr = malloc(sizeof(int));
free(ptr);
*ptr = 5; // use-after-free — undefined behavior
Set ptr = NULL after freeing.
5. Confusing = with == in conditions
if (x = 5) // assignment, always true!
if (x == 5) // comparison, correct
6. Buffer overflow with string functions
gets() is unsafe and was removed from C11. Always use fgets() with a size limit.
Practice Questions
What does
sizeof(int)return? Usually 4 bytes, but it’s platform-dependent. Always usesizeofinstead of hardcoding sizes.What is the difference between
mallocandcalloc?mallocallocates uninitialized memory.callocallocates and zero-initializes. Both returnvoid *.How do you prevent buffer overflow in C? Use bounded functions like
fgets,strncpy,snprintfinstead of their unbounded counterparts.What does
*do in a pointer declaration vs. dereference? Inint *p,*declares a pointer. In*p = 5,*dereferences it. Same symbol, different meaning by context.What is a segmentation fault? Accessing memory your program doesn’t own — reading past an array, dereferencing NULL, or writing to read-only memory.
Challenge: Write a C program that reads integers from a file into a dynamically allocated array, sorts them with qsort, and writes the sorted result to a new file.
Mini Project — File Size Analyzer
Build a tool that scans a directory, reports each file’s size in human-readable format, and calculates total disk usage.
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
void print_size(long bytes) {
if (bytes < 1024)
printf("%ld B", bytes);
else if (bytes < 1024 * 1024)
printf("%.1f KB", bytes / 1024.0);
else
printf("%.1f MB", bytes / (1024.0 * 1024.0));
}
int main(int argc, char *argv[]) {
const char *path = (argc > 1) ? argv[1] : ".";
DIR *dir = opendir(path);
if (dir == NULL) {
printf("Cannot open directory: %s\n", path);
return 1;
}
struct dirent *entry;
long total = 0;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') continue; // skip hidden files
struct stat st;
char fullpath[1024];
snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
if (stat(fullpath, &st) == 0) {
printf("%-30s ", entry->d_name);
print_size(st.st_size);
printf("\n");
total += st.st_size;
}
}
printf("------------------------\n");
printf("%-30s ", "Total");
print_size(total);
printf("\n");
closedir(dir);
return 0;
}FAQ
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro