1 · Format Specifiers (printf / scanf)
SpecTypeNote
%d / %iint (signed)decimal
%uunsigned intdecimal
%ld / %lulong / unsigned long
%ffloat/double (printf)6 dec default
%lfdouble (scanf only)use %f for float
%e / %gfloat/doublesci / shorter
%ccharsingle char
%schar * (string)null-terminated
%pvoid * (pointer)hex address
%x / %ounsigned inthex / octal
%zusize_tsizeof results
%%literal %
/* width.precision flags */ printf("%8.2f", 3.14); // " 3.14" printf("%-8d", 42); // "42 " left-align printf("%05d", 42); // "00042" zero-pad
2 · Pointer Cheat Sheet
OperationSyntax
Declare pointerint *p;
Address-ofp = &x;
Dereference (read)val = *p;
Dereference (write)*p = 42;
Pointer arithmeticp++; p+2; p-q
Array via pointer*(p+i) == p[i]
Null checkif (p != NULL)
Void pointervoid *v = malloc(n);
Pointer to pointerint **pp = &p;
/* Function pointer */ int (*fn)(int, int); // declaration fn = add; // assign result = fn(2, 3); // call /* typedef version */ typedef int (*Op)(int,int);
3 · String Functions <string.h>
SignatureNotes
strlen(s)length excl. \0
strcpy(dst,src)unsafe — no bounds
strncpy(dst,src,n)copies n bytes; may not null-terminate!
strcat(dst,src)unsafe — no bounds
strncat(dst,src,n)appends n chars + \0
strcmp(a,b)<0 / 0 / >0
strncmp(a,b,n)compare first n chars
strchr(s,c)ptr to first c or NULL
strstr(hay,ndl)ptr to first match or NULL
sprintf(buf,fmt,…)write to string buf
sscanf(s,fmt,…)parse from string
strtol(s,&end,base)safe atoi; base 10/16/0=auto
strtod(s,&end)safe atof → double
rand()random [0,RAND_MAX]; seed: srand(time(NULL))
4 · Memory Functions
SignatureNotes
malloc(size)uninitialized; NULL on fail
calloc(n,size)n*size, zero-initialized
realloc(ptr,size)may move; assign to tmp first!
free(ptr)ptr must be from malloc/calloc/realloc
memcpy(dst,src,n)copy n bytes; no overlap allowed
memmove(dst,src,n)overlap-safe copy
memset(ptr,val,n)fill n bytes with val (byte)
int *p = malloc(n * sizeof(int)); if (!p) { perror("malloc"); exit(1); } /* … use p … */ free(p); p = NULL; // NULL after free!
5 · File I/O <stdio.h>
ModeMeaning
"r"read; file must exist
"w"write; create/truncate
"a"append; create if absent
"r+"read+write; must exist
"w+"read+write; truncate
"b"binary flag (e.g. "rb")
fopen(path, mode)
Returns FILE* or NULL on error
fclose(fp)
Flush + close; returns 0 or EOF
fread(buf,sz,n,fp)
Read n items of sz bytes
fwrite(buf,sz,n,fp)
Write n items; returns items written
fgets(buf,n,fp)
Read line; keeps \n; null-terminates
fputs(s,fp)
Write string (no \n added)
fprintf(fp,fmt,…)
printf to file
fscanf(fp,fmt,…)
scanf from file
fseek(fp,off,whence)
SEEK_SET / SEEK_CUR / SEEK_END
ftell(fp)
Current byte offset
feof(fp) / ferror(fp)
Check EOF / error flag
6 · Process Syscalls
pid_t fork(void)
Create child. Returns child PID to parent, 0 to child, -1 on error.
execvp(file, argv[]) / execve(path, argv, envp)
Replace process image. Only returns on error (-1).
pid_t wait(int *status)
Wait for any child. Use WIFEXITED(s), WEXITSTATUS(s).
pid_t waitpid(pid, &status, opts)
Wait for specific child. opts: 0 (block) or WNOHANG (non-blocking).
getpid() / getppid()
Current PID / parent PID.
exit(status) / _exit(status)
exit flushes buffers; _exit does not (use in child after fork).
kill(pid, sig)
Send signal to process. kill(pid, SIGTERM) to terminate politely.
signal(signum, handler)
Install signal handler. Prefer sigaction() for portability.
pid_t pid = fork(); if (pid == 0) { execvp("ls", args); _exit(1); } else { waitpid(pid, &status, 0); }
7 · Low-level I/O (file descriptors)
open(path, flags [, mode])
Flags: O_RDONLY O_WRONLY O_RDWR O_CREAT O_TRUNC O_APPEND. Returns fd or -1.
read(fd, buf, count)
Returns bytes read (0 = EOF, -1 = error). May return less than count (short read).
write(fd, buf, count)
Returns bytes written or -1. Loop if short write needed.
close(fd)
Always close every fd. Returns 0 or -1.
lseek(fd, offset, whence)
SEEK_SET / SEEK_CUR / SEEK_END. Returns new offset.
dup(fd)
Copy fd to lowest available number.
dup2(oldfd, newfd)
Copy oldfd to newfd; closes newfd first. Used to redirect stdio.
/* Redirect stdout to file */ int fd = open("out.txt", O_WRONLY|O_CREAT, 0644); dup2(fd, STDOUT_FILENO); close(fd);
8 · Signals
SignalCause / Default
SIGINT (2)Ctrl+C → terminate
SIGTERM (15)polite kill → terminate
SIGKILL (9)force kill → cannot catch/ignore
SIGSEGV (11)bad memory access → core dump
SIGCHLD (17)child stopped/exited → ignore
SIGPIPE (13)write to closed pipe → terminate
SIGALRM (14)alarm() timer expired → terminate
/* Simple handler */ void handler(int sig) { cleanup(); exit(0); } signal(SIGINT, handler); /* Robust (sigaction) */ struct sigaction sa = {0}; sa.sa_handler = handler; sigaction(SIGINT, &sa, NULL);
9 · pthreads <pthread.h>
pthread_create(&tid, NULL, fn, arg)
Create thread running fn(arg). Returns 0 on success.
pthread_join(tid, &retval)
Wait for thread; retrieve return value. Must join or detach every thread.
pthread_exit(retval)
Terminate calling thread (does not kill process).
pthread_mutex_init(&mtx, NULL)
Initialise mutex (or use PTHREAD_MUTEX_INITIALIZER).
pthread_mutex_lock(&mtx) / unlock
Lock blocks if held; unlock releases. Always unlock every lock path.
pthread_mutex_destroy(&mtx)
Free mutex resources when no longer needed.
sem_init(&sem, 0, val)
Init semaphore (0 = thread-shared, val = initial count).
sem_wait(&sem) / sem_post(&sem)
Decrement (blocks at 0) / increment + wake one waiter.
sem_destroy(&sem)
Free semaphore. Link with -lpthread.
pthread_rwlock_t rw
pthread_rwlock_rdlock(&rw) — shared read lock; pthread_rwlock_wrlock(&rw) — exclusive write lock; pthread_rwlock_unlock(&rw) — release.
pthread_cond_t cv
pthread_cond_wait(&cv, &m) — atomically release mutex & sleep; pthread_cond_signal(&cv) — wake one waiter; pthread_cond_broadcast(&cv) — wake all.
10 · Makefile Patterns
# Variables CC = gcc CFLAGS = -Wall -Wextra -g OBJS = main.o utils.o # Rule: target : prerequisites prog: $(OBJS) $(CC) $(CFLAGS) -o $@ $^ %.o: %.c # pattern rule $(CC) $(CFLAGS) -c -o $@ $< # Automatic variables # $@ — target name # $< — first prerequisite # $^ — all prerequisites # $* — stem (matched by %) .PHONY: clean test clean: rm -f $(OBJS) prog test: prog ./prog | diff - expected.txt
11 · GDB Commands
CommandAction
break mainbreakpoint at function / line
break file.c:42breakpoint at specific line
run [args]start / restart program
next (n)step over one line
step (s)step into function call
continue (c)continue to next breakpoint
print expr (p)evaluate & print expression
x/4xw &varexamine memory (4 words, hex)
backtrace (bt)show call stack
info localslist local variables
watch varbreak when var changes
list (l)show source around current line
quit (q)exit gdb
gcc -g -o prog main.c # -g required! gdb ./prog (gdb) break main (gdb) run (gdb) print argv[0] (gdb) backtrace
12 · Valgrind — Memcheck
valgrind \ --leak-check=full \ --show-leak-kinds=all \ --track-origins=yes \ --verbose \ ./prog arg1 arg2
CategoryMeaning
definitely lostno pointer to block — real leak
indirectly lostonly reachable via lost block
still reachablepointed to at exit — often OK
Invalid read/writeout of bounds or freed memory
Uninit valueusing uninitialized memory
  • Always compile with -g for file/line info
  • Use --error-exitcode=1 in test scripts
  • ~10–50× slower than normal execution
13 · Common Pitfalls
  • Missing null terminator: char buf[5]="hello" — no room for \0
  • scanf without &: scanf("%d", x) — must be &x
  • %f vs %lf in scanf: use %lf for double; %f for float
  • Double free: calling free(p) twice corrupts the heap
  • Dangling pointer: using p after free(p) — set p=NULL
  • Not closing pipe ends: forgetting to close unused pipe fds causes read() to never see EOF
  • Zombie processes: forgetting to waitpid() after child exits
  • Not checking malloc: malloc returns NULL on failure — always check
  • Integer overflow: int wraps silently — use long or check bounds
  • getchar() as char: store in int, not char — EOF (-1) truncated
  • Array decay in sizeof: sizeof(arr) inside function gets pointer size, not array size
  • Race condition: reading shared data without a lock — always use mutex around shared state
  • Deadlock via wrong lock order: always acquire multiple mutexes in the same global order
  • exec after fork — double flush: use _exit() not exit() in child to avoid flushing parent's buffers
  • Off-by-one in strncpy: if n == strlen(src), null terminator is not copied — add 1 or manually set last byte to \0
  • Signed/unsigned comparison: comparing int and size_t — compiler may warn; cast appropriately
14 · Math Library <math.h>
FunctionNotes
sqrt(x)square root
pow(x,y)x to the power y
fabs(x)absolute value (double)
floor(x)round down
ceil(x)round up
round(x)round to nearest integer
log(x)natural log (ln)
log2(x)base-2 logarithm
exp(x)e^x
sin(x) / cos(x) / tan(x)trig (radians)
M_PI3.14159… (define _USE_MATH_DEFINES on MSVC)
INFINITY / NANIEEE special values
  • Link with -lm (e.g. gcc main.c -lm)
15 · Character Functions <ctype.h>
FunctionTrue when…
isalpha(c)letter (a–z, A–Z)
isdigit(c)digit (0–9)
isalnum(c)letter or digit
isspace(c)whitespace (space, \t, \n, …)
isupper(c)uppercase letter
islower(c)lowercase letter
isprint(c)printable character
toupper(c)→ uppercase equivalent
tolower(c)→ lowercase equivalent
  • All take int c — cast char: (unsigned char)c first to avoid UB
16 · GCC Compiler Flags
Flag(s)Effect
-Wall -Wextra -Wpedanticenable most warnings
-Werrortreat warnings as errors
-gdebug symbols (for gdb/valgrind)
-O0 / -O1 / -O2 / -O3optimization levels (0=none, 3=max)
-fsanitize=addressASan — memory errors (heap/stack)
-fsanitize=memoryMSan — uninit reads (Clang only)
-fsanitize=threadTSan — data races
-fsanitize=undefinedUBSan — undefined behaviour
-lmlink math library
-pthreadlink pthreads + enable thread macros
-Wvlawarn on variable-length arrays
-std=c11 / -std=c2xselect C standard
17 · IPC: fork + pipe pattern
int fd[2]; pipe(fd); // fd[0]=read, fd[1]=write if (fork() == 0) { close(fd[0]); // child: close read end write(fd[1], "hi", 2); close(fd[1]); _exit(0); } else { close(fd[1]); // parent: close write end char buf[64]; read(fd[0], buf, sizeof(buf)); wait(NULL); } // ── Shared memory (POSIX) ── // shm_open("/name", O_CREAT|O_RDWR, 0666) → fd // ftruncate(fd, size) // mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0) // munmap(ptr, size); shm_unlink("/name")