C Cheatsheet
C rewards precision: types, memory, and undefined behavior matter. This sheet collects the patterns you reach for most often while learning.
Pair it with the C tutorials for install steps, longer explanations, and safer habits around pointers and allocation.
Full lessons: C Tutorials
Compile & run
gcc one-liner
Compile a source file to an executable, then run it. -Wall enables useful warnings.
gcc -Wall -o hello hello.c
./hello
main
Program entry point. Return 0 for success. argc/argv receive command-line arguments.
#include <stdio.h>
int main(void) {
printf("Hello\n");
return 0;
}
Headers
#include pulls declarations. Angle brackets for system headers; quotes for your own.
#include <stdio.h>
#include <stdlib.h>
#include "util.h"
Makefile sketch
Automate compile rules. make rebuilds only what changed when dependencies are listed.
CC=gcc
CFLAGS=-Wall -g
hello: hello.c
$(CC) $(CFLAGS) -o hello hello.c
printf / scanf
Formatted output and input. Always check scanf's return value in real programs.
int n;
printf("n = ");
if (scanf("%d", &n) == 1) {
printf("got %d\n", n);
}
Types & operators
Basic types
int, long, short, char, float, double, and _Bool (or bool with
int count = 3;
double pi = 3.14;
char letter = 'A';
_Bool ok = 1;
sizeof
Yields the size in bytes of a type or expression. Result has type size_t.
#include <stdio.h>
printf("%zu\n", sizeof(int));
printf("%zu\n", sizeof(double));
Arithmetic & assignment
+ - * / % plus compound assignment. Integer division truncates toward zero.
int a = 10;
a += 2;
int q = a / 4; /* 3 */
Comparison & logic
Relational operators yield 0 or 1. && and || short-circuit; ! negates.
int x = 5;
if (x > 0 && x < 10) {
/* ... */
}
Casts
Explicit conversion between types. Prefer casts that widen; narrowing can lose data.
double d = 9.7;
int n = (int)d; /* 9 */
Control flow
if / else
Branch on a nonzero condition. Zero is false; any other value is true.
int score = 85;
if (score >= 90) {
puts("A");
} else if (score >= 80) {
puts("B");
} else {
puts("C");
}
switch
Jump among integer/enum case labels. Use break unless you intentionally fall through.
int day = 2;
switch (day) {
case 1: puts("Mon"); break;
case 2: puts("Tue"); break;
default: puts("Other"); break;
}
for / while
for is common for counted loops; while for condition-driven loops.
for (int i = 0; i < 3; i++) {
printf("%d\n", i);
}
int n = 3;
while (n > 0) {
printf("%d\n", n--);
}
break / continue
break exits the nearest loop or switch; continue starts the next loop iteration.
for (int i = 0; i < 10; i++) {
if (i % 2) continue;
if (i > 6) break;
printf("%d\n", i);
}
Functions & arrays
Function definition
Return type, name, and parameters. Prototypes in headers let callers see the signature first.
int add(int a, int b) {
return a + b;
}
int main(void) {
return add(2, 3) == 5 ? 0 : 1;
}
Pass by value
Arguments are copied. To modify the caller's variable, pass a pointer.
void bump(int *p) {
(*p)++;
}
int x = 1;
bump(&x); /* x is 2 */
Arrays
Contiguous elements of one type. Name decays to a pointer to the first element in most expressions.
int nums[3] = {3, 1, 4};
printf("%d\n", nums[0]);
nums[1] = 2;
Array length habit
C arrays do not store length. Pass a count alongside the pointer, or use a sentinel.
void print_ints(const int *a, size_t n) {
for (size_t i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
}
2D arrays
Array of arrays. Contiguous row-major layout; pass dimensions carefully to functions.
int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};
printf("%d\n", grid[1][0]); /* 4 */
Pointers & memory
& and *
& takes an address; * dereferences a pointer. Pointer type must match the object pointed to.
int x = 10;
int *p = &x;
printf("%d\n", *p);
*p = 20; /* x is 20 */
NULL
Null pointer constant. Check pointers from allocation or optional results before dereferencing.
int *p = NULL;
if (p == NULL) {
puts("no object");
}
malloc / free
Allocate heap memory and release it. Always free what you malloc; set pointers to NULL after free if reused.
#include <stdlib.h>
int *a = malloc(3 * sizeof *a);
if (!a) return 1;
a[0] = 1;
free(a);
a = NULL;
Pointer arithmetic
p + 1 advances by one element of *p's type, not one byte. Prefer array indexing for clarity.
int nums[] = {10, 20, 30};
int *p = nums;
printf("%d\n", *(p + 1)); /* 20 */
Undefined behavior (reminder)
Out-of-bounds access, use-after-free, and signed overflow are undefined—compilers assume they never happen.
/* Avoid: */
/* int a[2]; a[2] = 1; */
/* free(p); *p = 1; */
Strings & structs
C strings
char arrays ending in '\0'. Use string.h helpers; never forget space for the terminator.
#include <stdio.h>
#include <string.h>
char name[16] = "Ada";
printf("%zu\n", strlen(name));
strcpy / snprintf
Prefer bounded copies. snprintf writes at most size-1 chars and always null-terminates when size > 0.
char buf[8];
snprintf(buf, sizeof buf, "%s", "hello");
struct
Groups related fields under one type. Access members with . or -> via a pointer.
struct Point {
int x;
int y;
};
struct Point p = {3, 4};
struct Point *q = &p;
printf("%d\n", q->x);
typedef
Creates an alias for a type name, often for structs or function pointers.
typedef struct {
int x;
int y;
} Point;
Point p = {1, 2};
File I/O sketch
fopen / fscanf / fprintf / fclose for text files. Always check fopen for NULL.
#include <stdio.h>
FILE *f = fopen("out.txt", "w");
if (!f) return 1;
fprintf(f, "hi\n");
fclose(f);
Comments
One comment per signed-in account. Comments are saved with this page’s URL.