C Programming Cheat Sheet

c-programming Last verified: 29 Jul 2026

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
}
CommandEffect
gcc file.c -o outCompile + link β†’ executable
gcc -c file.cCompile to object file (.o)
gcc -S file.cCompile to assembly (.s)
gcc file.c -Wall -WextraEnable warnings
./outRun the program

Key headers

HeaderProvides
stdio.hprintf, scanf, fopen, fclose, fgets
stdlib.hmalloc, calloc, free, exit, atoi, qsort
string.hstrlen, strcpy, strcat, strcmp, strstr
math.hsqrt, pow, sin, cos, ceil, floor (link -lm)
ctype.hisalpha, isdigit, toupper, tolower

Data types & variables

TypeSizeFormatNotes
char1 B%c / %d-128 to 127
unsigned char1 B%u0 to 255
short2 B%hd-32768 to 32767
int4 B%d~-2.1B to 2.1B
unsigned int4 B%u0 to ~4.3B
long4/8 B%ldplatform dependent
long long8 B%lldlarge integers
float4 B%f~7 digit precision
double8 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

SpecifierType
%d / %iint
%uunsigned
%ffloat/double
%escientific
%cchar
%sstring
%ppointer
%x / %Xhex
%ooctal
%ldlong
%lldlong long
%zusize_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
PropertyStructureUnion
MemorySum of all membersSize of largest member
Active membersAll at onceOnly 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

OperatorMeaning
&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

ClassScopeLifetimeDefault value
autoblockblockgarbage
registerblockblockgarbage (CPU-register hint)
staticblock/filewhole program0
externfile/globalwhole program0

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)

AlgorithmIdeaTime
Selection sortRepeatedly find min, swap into placeO(nΒ²)
Bubble sortRepeatedly swap adjacent out-of-order pairsO(nΒ²)
Merge sortDivide, sort halves, mergeO(n log n)
Quick sortPartition around a pivot, recurseO(n log n) avg
Linear searchScan every elementO(n)
Binary searchHalve the range on a sorted arrayO(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

ExpressionMeaning
arraddress of first element (constant, cannot be reassigned)
*arrvalue of first element
arr[i]value at index i
&arr[i]address of element i
p = arrp 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

TrapRule
Missing & in scanfForgetting & before a variable in scanf causes crashes or garbage reads.
String comparisonComparing strings with == compares pointers, not contents β€” use strcmp.
Loop boundsOff-by-one errors, especially <= vs < on array bounds.
Returning a local addressReturning the address of a stack variable is invalid β€” it no longer exists after the function returns.
Memory leaks / use-after-freeForgetting to free allocated memory, or using memory after it’s freed.
Missing breakA missing break in a switch causes unintended fallthrough.
Integer division truncation5 / 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 functionsgets/strcpy without a size limit risk buffer overflows β€” prefer the bounded variants.

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

Frequently Asked Questions

1 Is C programming important for C-CAT?

Yes, C programming carries significant weightage in Section A of C-CAT exam.

2 Which topics in C are most asked?

Pointers, arrays, strings, structures, and dynamic memory allocation are frequently tested.