C Language
pointers · memory · structs · arrays · strings · functions · control flow · file I/O
Sheet 1 of 3
C99 / C11
Beginner
Printable
Data Types & Variables
| Type | Size (typical) | Range / Notes | Example |
|---|---|---|---|
| char | 1 byte | -128 to 127 (or 0–255 unsigned) | char c = 'A'; |
| int | 4 bytes | -2,147,483,648 to 2,147,483,647 | int n = 42; |
| short | 2 bytes | -32,768 to 32,767 | short s = 100; |
| long | 4–8 bytes | At least 32 bits | long l = 100000L; |
| long long | 8 bytes | -9.2×10¹⁸ to 9.2×10¹⁸ | long long ll = 9LL; |
| float | 4 bytes | ~7 decimal digits precision | float f = 3.14f; |
| double | 8 bytes | ~15 decimal digits precision | double d = 3.14; |
| unsigned int | 4 bytes | 0 to 4,294,967,295 | unsigned int u = 42U; |
| void | — | No value; used for pointers & functions | void *ptr; |
Variable Declaration & Preprocessor
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 /* constant macro */ #define PI 3.14159 #define SQ(x) ((x)*(x)) /* function macro */ int a = 10; /* global */ const int SIZE = 50; /* immutable */ static int count = 0; /* file-scoped */ int x, y, z; /* multiple declare */
Arrays
1D Arrays
/* Declare and initialise */ int nums[5] = {10, 20, 30, 40, 50}; int zeros[10] = {0}; /* all zeros */ char name[] = "Alice"; /* size inferred */ /* Access — 0-indexed */ nums[0] /* 10 — first */ nums[4] /* 50 — last */ /* Length via sizeof */ int len = sizeof(nums) / sizeof(nums[0]); /* len = 5 */ /* Iterate */ for (int i = 0; i < len; i++) printf("%d\n", nums[i]);
2D Arrays & Multidimensional
/* 3 rows × 4 cols */ int grid[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; grid[1][2] /* 7 */ /* Nested loop */ for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) printf("%d ", grid[r][c]);
No bounds checking! Accessing arr[10] on a 5-element array is undefined behaviour — C won't warn you. Always track array sizes manually.
Strings
Create & Print
/* String = char array ending in '\0' */ char s1[] = "Hello"; /* on stack */ char s2[20] = "World"; /* fixed buffer */ char *s3 = "literal"; /* read-only! */ printf("%s\n", s1); printf("len=%zu\n", strlen(s1)); /* 5 */
string.h Functions
#include <string.h> strlen(s) /* length (excl. \0) */ strcpy(dst, src) /* copy src → dst */ strncpy(dst, src, n) /* safe copy n chars */ strcat(dst, src) /* append src to dst */ strncat(dst, src, n) /* safe append */ strcmp(a, b) /* 0 if equal */ strncmp(a, b, n) /* compare n chars */ strchr(s, c) /* find char in str */ strstr(s, sub) /* find substring */ sprintf(buf, "%d", n) /* int → string */ sscanf(s, "%d", &n) /* string → int */
Never use strcpy/strcat on untrusted input — they can overflow. Prefer strncpy, strncat, or the safer snprintf.
Pointers
Basics — & and *
int x = 42; int *p = &x; /* p = address of x */ printf("%p\n", (void*)p); /* address */ printf("%d\n", *p); /* 42 — dereference */ *p = 100; /* modifies x! */ printf("%d\n", x); /* 100 */ /* NULL pointer — safe default */ int *safe = NULL; if (safe != NULL) *safe = 1;
Pointer Arithmetic & Arrays
int arr[] = {10, 20, 30, 40}; int *p = arr; /* &arr[0] */ *p /* 10 */ *(p+1) /* 20 */ *(p+2) /* 30 — same as arr[2] */ p++; /* advance to next int */ *p /* 20 now */ /* Pointer difference */ int *start = arr; int *end = arr + 4; end - start; /* 4 elements */
Pointer to Pointer & Function Pointer
/* Double pointer */ int val = 5; int *p = &val; int **pp = &p; **pp /* 5 */ /* Function pointer */ int add(int a, int b) { return a+b; } int (*fp)(int,int) = add; fp(3, 4) /* 7 */ /* Cleaner with typedef */ typedef int (*MathFn)(int,int); MathFn fn = add;
Dangling pointers: Never dereference a pointer after free(). Set it to NULL immediately after freeing. Never return a pointer to a local variable — it's destroyed when the function returns.
Memory Management
malloc · calloc · free
#include <stdlib.h> /* malloc — raw uninitialized memory */ int *arr = malloc(5 * sizeof(int)); if (arr == NULL) { perror("malloc failed"); return 1; } /* calloc — zero-initialised */ int *arr2 = calloc(5, sizeof(int)); /* Use it */ arr[0] = 10; arr[1] = 20; /* ALWAYS free heap memory */ free(arr); arr = NULL; /* prevent dangling */ free(arr2); arr2 = NULL;
realloc — resize heap block
/* Start with 5 ints */ int *buf = malloc(5 * sizeof(int)); /* Grow to 10 ints */ int *tmp = realloc(buf, 10 * sizeof(int)); if (tmp == NULL) { free(buf); /* original freed */ return 1; } buf = tmp; /* Dynamic string builder */ char *s = malloc(16); snprintf(s, 16, "%s", "hello"); free(s);
Stack vs Heap
/* STACK — automatic, fast, limited */ void foo() { int local = 5; /* stack */ int arr[100]; /* stack */ } /* freed automatically */ /* HEAP — manual, large, persistent */ int *big = malloc(1024 * 1024); /* survives past function return */ free(big); /* you must free it */
| Stack | Heap | |
|---|---|---|
| Speed | Very fast | Slower |
| Size | Limited (~8MB) | Large (GBs) |
| Lifetime | Function scope | Until free() |
| Managed by | Compiler | You |
Memory leaks happen when you allocate with malloc but never call free. Use tools like Valgrind or AddressSanitizer (-fsanitize=address) to detect them.
Structs
Define & Use
/* Define a struct type */ struct Point { int x; int y; }; /* Typedef — cleaner names */ typedef struct { char name[50]; int age; double score; } Student; /* Declare and initialise */ Student s1 = {"Alice", 20, 95.5}; Student s2 = { .name = "Bob", /* designated */ .age = 22, .score = 87.0 }; printf("%s: %.1f\n", s1.name, s1.score);
Struct Pointer & Arrow Operator
Student *sp = &s1; /* Two equivalent ways to access */ (*sp).age /* dereference then . */ sp->age /* arrow — shorthand */ sp->score = 99.0; /* modify */ /* Heap-allocated struct */ Student *hp = malloc(sizeof(Student)); strcpy(hp->name, "Carol"); hp->age = 21; free(hp);
Functions
Declare, Define, Call
/* Prototype (forward declaration) */ int add(int a, int b); void greet(const char *name); /* Definition */ int add(int a, int b) { return a + b; } void greet(const char *name) { printf("Hello, %s!\n", name); } /* Call */ int result = add(3, 4); /* 7 */ greet("Alice");
Pass by Value vs Pass by Pointer
/* Pass by VALUE — copy, original unchanged */ void double_val(int n) { n *= 2; } int x = 5; double_val(x); /* x still 5 */ /* Pass by POINTER — modifies original */ void double_ptr(int *n) { *n *= 2; } double_ptr(&x); /* x is now 10 */ /* Returning multiple values via pointers */ void min_max(int *arr, int n, int *mn, int *mx) { *mn = *mx = arr[0]; for (int i=1; i<n; i++) { if (arr[i] < *mn) *mn = arr[i]; if (arr[i] > *mx) *mx = arr[i]; } }
Control Flow
if / else if / else & switch
int score = 85; if (score >= 90) printf("A\n"); else if (score >= 80) printf("B\n"); /* prints B */ else printf("C\n"); /* switch — integer / char only */ switch (score / 10) { case 10: case 9: printf("A"); break; case 8: printf("B"); break; default: printf("C"); }
for · while · do-while
/* for loop */ for (int i = 0; i < 5; i++) printf("%d\n", i); /* while loop */ int n = 1; while (n <= 10) { printf("%d ", n); n++; } /* do-while — runs at least once */ do { printf("Enter > 0: "); scanf("%d", &n); } while (n <= 0); /* break and continue */ for (int i=0; i<10; i++) { if (i == 3) continue; /* skip 3 */ if (i == 7) break; /* stop at 7 */ }
printf / scanf Format Specifiers
/* printf specifiers */ printf("%d", n); /* int */ printf("%ld", l); /* long */ printf("%lld", ll); /* long long */ printf("%u", u); /* unsigned int */ printf("%f", f); /* float/double */ printf("%.2f", f); /* 2 decimals */ printf("%s", s); /* string */ printf("%c", c); /* char */ printf("%p", p); /* pointer addr */ printf("%zu", sz); /* size_t */ printf("%05d", n); /* zero-pad 5 */ printf("%-10s",s); /* left-align */
File I/O
Read & Write Text Files
#include <stdio.h> /* Write to a file */ FILE *fp = fopen("out.txt", "w"); if (fp) { fprintf(fp, "Hello, File!\n"); fclose(fp); } /* Read line by line */ FILE *fr = fopen("out.txt", "r"); char buf[256]; while (fgets(buf, sizeof(buf), fr)) printf("%s", buf); fclose(fr); /* Modes: "r" "w" "a" "rb" "wb" */
Always check fopen! If the file doesn't exist or permissions are wrong, fopen returns NULL. Always check before reading or writing.
enum, typedef & union
enum
/* Starts at 0 by default */ typedef enum { MON, TUE, WED, THU, FRI, SAT, SUN } Day; Day today = WED; printf("%d\n", today); /* 2 */ /* Custom values */ typedef enum { OK = 200, NOT_FOUND = 404, ERROR = 500 } HttpStatus;
union
/* All members share same memory */ typedef union { int i; float f; char bytes[4]; } Data; Data d; d.i = 42; /* d.f now has garbage — only */ /* the last-written member valid */ printf("%zu\n", sizeof(d)); /* 4 */
C Language Mastery Checklist
| Arrays & Strings | Key point |
|---|---|
| Declare a 1D array | int a[5] = {0}; |
| Get array length | sizeof(a)/sizeof(a[0]) |
| String length | strlen(s) |
| Safe string copy | strncpy(dst,src,n) |
| Compare strings | strcmp(a,b) == 0 |
| Pointers & Memory | Key point |
|---|---|
| Get address of var | &variable |
| Dereference pointer | *ptr |
| Heap allocate | malloc(n * sizeof(T)) |
| Zero-initialise heap | calloc(n, sizeof(T)) |
| Free + nullify | free(p); p = NULL; |
| Structs & Functions | Key point |
|---|---|
| Define a struct | typedef struct { } T; |
| Arrow operator | ptr->field |
| Pass by pointer | fn(&var) |
| Function pointer | int (*fp)(int,int); |
| Open a file safely | if (fp = fopen(...)) |
Next up → Sheet 2: Cpp STL ·
vector · map · set · queue · iterator · algorithm · sort · find · transform