C Cheatsheet

Control Flow

Use this C reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

if / else

if (condition) {
    // executes when condition != 0
}

if (x > 0) {
    printf("positive\n");
} else if (x < 0) {
    printf("negative\n");
} else {
    printf("zero\n");
}

// Single-statement bodies (braces optional but recommended)
if (n == 0) return 0;

switch / case

switch (expression) {          // expression must be integer type
    case 1:
        printf("one\n");
        break;                 // without break, falls through
    case 2:
    case 3:                    // multiple cases share the same body
        printf("two or three\n");
        break;
    default:
        printf("other\n");
        break;                 // break in default is optional but good practice
}

Fall-through is intentional when explicit:

switch (c) {
    case 'a': case 'e': case 'i':
    case 'o': case 'u':
        vowel_count++;
        break;
    default:
        consonant_count++;
}

switch works on int, char, enum, and compatible integer types. Not on float, double, or strings.

while Loop

while (condition) {
    // body executes as long as condition != 0
}

int i = 0;
while (i < 10) {
    printf("%d\n", i);
    i++;
}

// Infinite loop
while (1) {
    if (done) break;
}

do-while Loop

Body executes at least once; condition checked after.

do {
    // body
} while (condition);

int n;
do {
    printf("Enter positive number: ");
    scanf("%d", &n);
} while (n <= 0);

for Loop

for (init; condition; update) {
    // body
}

for (int i = 0; i < 10; i++) {
    printf("%d\n", i);
}

// Multiple init/update with comma operator
for (int i = 0, j = 10; i < j; i++, j--) {
    printf("%d %d\n", i, j);
}

// Infinite loop
for (;;) {
    if (done) break;
}

// Iterate array
int arr[] = {1, 2, 3, 4, 5};
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++) {
    printf("%d\n", arr[i]);
}

break and continue

// break — exit the innermost loop or switch
for (int i = 0; i < 100; i++) {
    if (i == 5) break;       // stops when i reaches 5
}

// continue — skip rest of current iteration
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;  // skip even numbers
    printf("%d\n", i);
}

// Both apply to the INNERMOST enclosing loop/switch
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 1) break;   // breaks inner loop only
    }
}

goto

// goto jumps to a label in the same function
goto cleanup;

cleanup:
    free(buf);
    return -1;

// Common legitimate use: error cleanup in deeply nested code
int result = -1;
char *buf = malloc(256);
if (!buf) goto done;

FILE *f = fopen("file.txt", "r");
if (!f) goto free_buf;

// ... work ...
result = 0;

fclose(f);
free_buf:
    free(buf);
done:
    return result;

goto cannot jump into a block past variable initializations (C99+ restriction). Avoid for general control flow; error cleanup is its main legitimate use.

return

// Return from void function
void print_if_positive(int n) {
    if (n <= 0) return;       // early exit
    printf("%d\n", n);
}

// Return a value
int max(int a, int b) {
    return (a > b) ? a : b;
}

// In main: 0 = success, non-zero = failure
int main(void) {
    return 0;
    // or: return EXIT_SUCCESS; / return EXIT_FAILURE;
}

Conditional Expression (Ternary)

int abs_val = (x >= 0) ? x : -x;
const char *label = (count == 1) ? "item" : "items";

// Nested (readable only when shallow)
int sign = (x > 0) ? 1 : (x < 0) ? -1 : 0;

assert

#include <assert.h>

assert(ptr != NULL);          // aborts with message if condition is false
assert(index >= 0 && index < len);

// Disabled when compiled with -DNDEBUG
// Use for programmer errors, not user input validation

_Static_assert (C11+)

Compile-time assertion — no runtime cost.

_Static_assert(sizeof(int) == 4, "int must be 4 bytes");
_Static_assert(sizeof(long) >= 8, "need 64-bit long");

// C23 shorthand (no message required):
static_assert(sizeof(int) >= 2);

Common Patterns

// Guard clause (early return)
int process(int *data, int len) {
    if (!data || len <= 0) return -1;
    // ... main logic ...
    return 0;
}

// Loop with index and sentinel
while ((c = getchar()) != EOF && c != '\n') {
    buf[i++] = c;
}

// Iterate until null
const char *s = "hello";
while (*s) {
    putchar(*s++);
}

// Bounded retry loop
int retries = 3;
while (retries-- > 0) {
    if (try_operation() == 0) break;
}