CDAC C-CAT · NEXT CYCLE: FEBRUARY 2027 BATCH UPDATED JULY 2026

C Programming Cheat Sheet

Core C syntax, pointers, arrays, structures, memory management, and file handling — the complete C reference for CDAC C-CAT.

No login required
Cross-checked against syllabus
Updated July 2026
On this page

Program structure & compilation

#include <stdio.h>              // preprocessor directive
int global_var = 10;            // global (optional)

int main(int argc, char *argv[]) {
    int x = 5;
    printf("x = %d\n", x);
    return 0;                   // 0 = success
}
Command Effect
gcc file.c -o out Compile + link → executable
gcc -c file.c Compile to object file (.o)
gcc -S file.c Compile to assembly (.s)
gcc file.c -Wall -Wextra Enable warnings
./out Run the program

Key headers

Header Provides
stdio.h printf, scanf, fopen, fclose, fgets
stdlib.h malloc, calloc, free, exit, atoi, qsort
string.h strlen, strcpy, strcat, strcmp, strstr
math.h sqrt, pow, sin, cos, ceil, floor (link -lm)
ctype.h isalpha, isdigit, toupper, tolower

Data types & variables

Type Size Format Notes
char 1 B %c / %d -128 to 127
unsigned char 1 B %u 0 to 255
short 2 B %hd -32768 to 32767
int 4 B %d ~-2.1B to 2.1B
unsigned int 4 B %u 0 to ~4.3B
long 4/8 B %ld platform dependent
long long 8 B %lld large integers
float 4 B %f ~7 digit precision
double 8 B %lf ~15 digit precision

Declaration & casting

int a = 10;
const int MAX_SIZE = 100;        // cannot be modified
int x = 3.7;                     // truncates -> 3
float y = 5;                     // widens -> 5.0
float fr = (float)a / b;         // explicit cast
printf("%zu\n", sizeof(int));    // sizeof operator -> 4

Input & output

printf("%d %.2f %s %c\n", num, pi, name, ch);
printf("%10d\n", num);   // right-aligned width 10
printf("%-10d|\n", num); // left-aligned
printf("%010d\n", num);  // zero-padded

scanf("%d", &age);       // & required for scalars
scanf("%49s", name);     // no & needed for arrays

char full[100];
fgets(full, sizeof(full), stdin);       // reads spaces too
full[strcspn(full, "\n")] = '\0';       // strip newline

sprintf(buf, "Age is %d", age);         // format into string
sscanf(data, "%d %f", &x, &y);          // parse from string

Format specifiers

Specifier Type
%d / %i int
%u unsigned
%f float/double
%e scientific
%c char
%s string
%p pointer
%x / %X hex
%o octal
%ld long
%lld long long
%zu size_t

Operators

  • Arithmetic: + - * / % (int / truncates toward zero)
  • Relational: == != < > <= >=
  • Logical: && || ! — short-circuit evaluated
  • Assignment: += -= *= /= %=
  • Increment: ++x pre (change then use), x++ post (use then change)
  • Ternary: cond ? valIfTrue : valIfFalse

Precedence (high → low, abbreviated): () [] -> . → unary ! ~ ++ -- * &* / %+ - → shifts << >> → relational → ==&^|&&||?:=

Control flow

Conditionals

if (score >= 60) { printf("Pass\n"); }
else if (score >= 40) { printf("Borderline\n"); }
else { printf("Fail\n"); }

switch (day) {
    case 1: printf("Mon"); break;
    case 6: case 7: printf("Weekend"); break;  // fallthrough
    default: printf("Invalid");
}

Loops

for (int i = 0; i < 5; i++) { printf("%d ", i); }
while (cond) { ... }
do { ... } while (cond);   // body runs at least once

for (int i = 0; i < 10; i++) {
    if (i == 5) break;        // exit loop entirely
    if (i % 2 == 0) continue; // skip to next iteration
    printf("%d ", i);
}

Functions

int add(int a, int b);                  // prototype (declare before use)
int add(int a, int b) { return a + b; } // definition

void swap(int *a, int *b) {   // pass by pointer to modify caller
    int t = *a; *a = *b; *b = t;
}

int main() {
    int x = 10, y = 20;
    swap(&x, &y);   // x=20, y=10
}

All C arguments are passed by value — pass a pointer to let a function modify the caller's variable. Good practice: return results instead of printing inside a function; take input as parameters instead of scanf inside.

Recursion

long long factorial(int n) {
    if (n == 0 || n == 1) return 1;    // base case
    return n * factorial(n - 1);       // recursive case
}

int fib(int n) {
    if (n <= 0) return 0;
    if (n == 1) return 1;
    return fib(n-1) + fib(n-2);        // O(2^n) - slow!
}

Every recursive function needs a base case and a recursive case that moves toward it. Naive recursive Fibonacci is exponential; an iterative version is O(n).

Arrays

int arr[5] = {1, 2, 3, 4, 5};
int mat[3][3] = {{1,2,3},{4,5,6},{7,8,9}};

void print_array(int arr[], int n) {   // decays to pointer
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
}
// arr[i] is equivalent to *(arr + i)
// array name = pointer to its first element

Strings

char s[] = "Hello";   // null-terminated: {'H','e','l','l','o','\0'}

strlen(s); strcpy(dst, s); strcat(dst, s); strcmp(a, b);
strstr(s, "sub"); strchr(s, 'l');
atoi("42"); atof("3.14");
toupper(c); tolower(c); isalpha(c); isdigit(c);

Prefer strncpy/strncat/fgets over the unbounded versions to avoid buffer overflows.

Pointers

int x = 42;
int *p = &x;              // & = address-of
printf("%d\n", *p);       // * = dereference -> 42

int **pp = &p;             // pointer to pointer
**pp = 99;                 // modifies x through pp

int *n = NULL;              // always check before dereferencing
if (n != NULL) { ... }

Pointer arithmetic

int arr[] = {10,20,30,40,50};
int *p = arr;
p++;      // now points to arr[1]
p += 2;   // now points to arr[3]

ptrdiff_t d = (&arr[4]) - (&arr[0]);  // d = 4 (element count)

Dynamic memory allocation

int *a = malloc(5 * sizeof(int));       // uninitialized memory
int *b = calloc(5, sizeof(int));        // zero-initialized memory
a = realloc(a, 10 * sizeof(int));       // resize existing block
if (a == NULL) { /* allocation failed */ exit(1); }
free(a); a = NULL;                      // always free; avoid leaks

A memory leak happens when allocated memory is never freed. Always pair every malloc/calloc with a matching free.

Structures, unions & enums

typedef struct {
    int id;
    char name[50];
    float gpa;
} student_t;

student_t s = {101, "Alice", 3.8};
s.gpa = 3.9;               // dot operator

student_t *p = &s;
p->gpa = 4.0;               // arrow operator (same as (*p).gpa)

union data { int i; float f; char str[20]; };  // members share memory

typedef enum { MON=1, TUE, WED, THU, FRI, SAT, SUN } weekday_t;  // auto-increments
Property Structure Union
Memory Sum of all members Size of largest member
Active members All at once Only one at a time

File handling

FILE *fp = fopen("data.txt", "w");   // r w a rb wb r+ w+
if (fp == NULL) { perror("fopen"); return 1; }
fprintf(fp, "Score: %.2f\n", 98.5);
fclose(fp);

fp = fopen("data.txt", "r");
char line[100];
while (fgets(line, sizeof(line), fp) != NULL) { printf("%s", line); }
fclose(fp);

fwrite(&rec, sizeof(rec), 1, fp);   // binary write
fread(&rec, sizeof(rec), 1, fp);    // binary read

fseek(fp, 0, SEEK_END);   // SEEK_SET / SEEK_CUR / SEEK_END
long size = ftell(fp);

Preprocessor directives

#define PI 3.14159
#define SQUARE(x) ((x) * (x))   // always parenthesize macro args

#ifdef DEBUG
    printf("debug info\n");
#endif

#ifndef HEADER_H    // include guard
#define HEADER_H
...
#endif

Bitwise operators

Operator Meaning
& AND
| OR
^ XOR
~ NOT
<< shift left (×2^n)
>> shift right (÷2^n)
n & 1              // check if odd (LSB test)
n | (1 << k)       // set bit k
n & ~(1 << k)      // clear bit k
n ^ (1 << k)       // toggle bit k
(n >> k) & 1       // read bit k
c ^ 32             // toggle ASCII letter case
a ^= b; b ^= a; a ^= b;   // swap two ints without a temp variable

Storage classes

Class Scope Lifetime Default value
auto block block garbage
register block block garbage (CPU-register hint)
static block/file whole program 0
extern file/global whole program 0

static local variables retain their value between function calls.

Command-line arguments

int main(int argc, char *argv[]) {
    // argc = number of arguments (includes program name)
    // argv[0] = program name, argv[1..] = actual arguments
    for (int i = 0; i < argc; i++) printf("%s\n", argv[i]);
}

Error handling

FILE *fp = fopen("missing.txt", "r");
if (fp == NULL) {
    perror("fopen");                    // prints readable error
    printf("%s\n", strerror(errno));    // errno.h
    return 1;
}
if (malloc(100) == NULL) exit(EXIT_FAILURE);

Sorting & searching (patterns)

Algorithm Idea Time
Selection sort Repeatedly find min, swap into place O(n²)
Bubble sort Repeatedly swap adjacent out-of-order pairs O(n²)
Merge sort Divide, sort halves, merge O(n log n)
Quick sort Partition around a pivot, recurse O(n log n) avg
Linear search Scan every element O(n)
Binary search Halve the range on a sorted array O(log n)
int binary_search(int arr[], int n, int target) {
    int lo = 0, hi = n - 1;
    while (lo <= hi) {
        int mid = lo + (hi - lo) / 2;
        if (arr[mid] == target) return mid;
        else if (arr[mid] < target) lo = mid + 1;
        else hi = mid - 1;
    }
    return -1;
}

Common standard library functions

// math.h (compile with -lm)
sqrt(x); pow(b,e); fabs(x); ceil(x); floor(x); round(x); log(x); log10(x);

// stdlib.h
srand(time(NULL)); rand();        // random numbers
int dice = rand() % 6 + 1;        // 1-6
exit(0); exit(EXIT_FAILURE);
qsort(arr, n, sizeof(int), cmp_func);

Quick revision summary

  • Pointers: int *p = &x; holds an address; *p dereferences it.
  • Arrays: arr[i] == *(arr + i); array name decays to a pointer when passed to functions.
  • Strings: null-terminated char arrays; always leave room for '\0'.
  • Memory: pair every malloc/calloc with free; check for NULL.
  • Structs: dot . for values, arrow -> for pointers to structs.
  • Functions: pass-by-value by default; use pointers to modify caller data.
  • Files: always check fopen for NULL and close with fclose.

Pointers vs arrays — side by side

Expression Meaning
arr address of first element (constant, cannot be reassigned)
*arr value of first element
arr[i] value at index i
&arr[i] address of element i
p = arr p is a pointer, CAN be reassigned / incremented
p[i] same as *(p + i)
sizeof(arr) total bytes of the array (compile-time size)
sizeof(p) size of the pointer itself (e.g. 8 bytes on 64-bit)

Worked examples

Reverse an array in place

void reverse(int arr[], int n) {
    int i = 0, j = n - 1;
    while (i < j) {
        int t = arr[i]; arr[i] = arr[j]; arr[j] = t;
        i++; j--;
    }
}

Find max and min with pointer outputs

void find_max_min(int arr[], int n, int *max, int *min) {
    *max = *min = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] > *max) *max = arr[i];
        if (arr[i] < *min) *min = arr[i];
    }
}
// call: find_max_min(arr, 5, &max, &min);

Count set bits

int count_ones(unsigned int n) {
    int count = 0;
    while (n != 0) { count += n & 1; n >>= 1; }
    return count;
}

Dynamic 2D array

int **m = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) m[i] = malloc(cols * sizeof(int));
// ... use m[i][j] ...
for (int i = 0; i < rows; i++) free(m[i]);
free(m);

CDAC C-CAT — top C programming traps

Trap Rule
Missing & in scanf Forgetting & before a variable in scanf causes crashes or garbage reads.
String comparison Comparing strings with == compares pointers, not contents — use strcmp.
Loop bounds Off-by-one errors, especially <= vs < on array bounds.
Returning a local address Returning the address of a stack variable is invalid — it no longer exists after the function returns.
Memory leaks / use-after-free Forgetting to free allocated memory, or using memory after it's freed.
Missing break A missing break in a switch causes unintended fallthrough.
Integer division truncation 5 / 2 is 2, not 2.5 — cast one operand to float if you need the decimal.
Unparenthesized macros #define SQ(x) x*x breaks for SQ(a+b) — always wrap macro parameters in parentheses.
Unbounded string functions gets/strcpy without a size limit risk buffer overflows — prefer the bounded variants.

PYQs are indicative of exam style, not guaranteed exact repeats.

AD SLOT — insert <ins class="adsbygoogle"> unit here once AdSense is approved