C Cheatsheet

Functions

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

Declaration and Definition

// Declaration (prototype) — tells the compiler the signature
int add(int a, int b);           // parameter names optional
int add(int, int);               // same

// Definition — the actual function body
int add(int a, int b) {
    return a + b;
}

// Combined (definition before first use — no separate prototype needed)
int square(int n) {
    return n * n;
}

Put prototypes in header files (util.h) and definitions in .c files (util.c).

Parameter Passing

C is always pass-by-value — functions receive copies of arguments.

void double_val(int x) {
    x *= 2;    // modifies the local copy only
}

// To modify the caller's variable, pass a pointer
void double_val_ptr(int *x) {
    *x *= 2;   // modifies the caller's int
}

int n = 5;
double_val(n);       // n still 5
double_val_ptr(&n);  // n is now 10

Passing Arrays

Arrays decay to a pointer to their first element when passed to functions.

// These three declarations are equivalent
void print_arr(int arr[], int len);
void print_arr(int *arr, int len);
void print_arr(int arr[10], int len);  // size hint is ignored

void print_arr(int arr[], int len) {
    for (int i = 0; i < len; i++)
        printf("%d\n", arr[i]);
}

int data[] = {1, 2, 3};
print_arr(data, 3);   // pass array and length

// 2D arrays: inner dimension required
void print_matrix(int m[][3], int rows);

// Variable-length array parameter (C99+)
void process(int n, int arr[n]);

Return Values

int max(int a, int b) { return (a > b) ? a : b; }
void log_msg(const char *s) { printf("%s\n", s); }  // void: no return value

// Return pointer — MUST point to static/heap memory, not a local
const char *greeting(void) {
    static char buf[64];
    snprintf(buf, sizeof(buf), "Hello");
    return buf;       // safe: static lifetime
}
// WRONG: return &local; — local is destroyed on return

Function Pointers

// Type: pointer to function taking two ints, returning int
int (*fp)(int, int);

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

fp = add;              // assign
int result = fp(3, 4); // call through pointer → 7
fp = &sub;             // & optional — function name decays to pointer

// typedef for cleaner syntax
typedef int (*BinOp)(int, int);
BinOp op = add;
printf("%d\n", op(3, 4));  // 7

// Passing function pointer as argument
void apply(int a, int b, int (*op)(int, int)) {
    printf("%d\n", op(a, b));
}
apply(3, 4, add);
apply(3, 4, sub);

// Array of function pointers
int (*ops[])(int, int) = {add, sub};
ops[0](5, 3);   // 8

// Returning a function pointer
int (*get_op(char c))(int, int) {
    return (c == '+') ? add : sub;
}

Variadic Functions (<stdarg.h>)

#include <stdarg.h>

// At least one fixed parameter required before ...
int sum(int count, ...) {
    va_list args;
    va_start(args, count);    // initialize; last fixed param
    int total = 0;
    for (int i = 0; i < count; i++) {
        total += va_arg(args, int);   // retrieve next arg as int
    }
    va_end(args);             // clean up
    return total;
}

sum(3, 10, 20, 30);   // 60

// Forwarding va_list to another variadic function
void my_printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);   // vprintf accepts va_list
    va_end(args);
}

Inline Functions (C99+)

// Hint to compiler to expand at call site — avoids function call overhead
static inline int abs_val(int x) {
    return (x < 0) ? -x : x;
}

// extern inline — one definition in the translation unit
extern inline int clamp(int v, int lo, int hi);

Recursion

int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

int fib(int n) {
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}

// Tail recursion (compiler may optimize to a loop)
int factorial_tail(int n, int acc) {
    if (n <= 1) return acc;
    return factorial_tail(n - 1, n * acc);
}

_Noreturn / noreturn (C11+)

#include <stdnoreturn.h>

noreturn void fatal(const char *msg) {
    fprintf(stderr, "Fatal: %s\n", msg);
    exit(EXIT_FAILURE);
}
// Compiler can omit return-path code and suppress warnings

Linkage and Visibility

// Internal linkage — only visible in this .c file
static int helper(void) { return 42; }

// External linkage (default for non-static functions)
int public_api(void) { return 1; }

// Declare external function defined elsewhere
extern int other_module_func(void);

Standard Library Function Signatures (Quick Reference)

<string.h> (see also arrays-and-strings page)

size_t strlen(const char *s);
char  *strcpy(char *dst, const char *src);
char  *strncpy(char *dst, const char *src, size_t n);
char  *strcat(char *dst, const char *src);
char  *strncat(char *dst, const char *src, size_t n);
int    strcmp(const char *a, const char *b);
int    strncmp(const char *a, const char *b, size_t n);
char  *strchr(const char *s, int c);
char  *strrchr(const char *s, int c);
char  *strstr(const char *haystack, const char *needle);
char  *strtok(char *s, const char *delim);         // not thread-safe
void  *memcpy(void *dst, const void *src, size_t n);
void  *memmove(void *dst, const void *src, size_t n); // safe overlap
void  *memset(void *s, int c, size_t n);
int    memcmp(const void *a, const void *b, size_t n);

<math.h> (link with -lm)

double sqrt(double x);        double cbrt(double x);
double pow(double x, double y);
double fabs(double x);        double fabsf(float x);
double floor(double x);       double ceil(double x);
double round(double x);       double trunc(double x);
double fmod(double x, double y);
double log(double x);         double log2(double x);   double log10(double x);
double exp(double x);         double exp2(double x);
double sin(double x);         double cos(double x);    double tan(double x);
double asin(double x);        double acos(double x);   double atan(double x);
double atan2(double y, double x);
double hypot(double x, double y);
int    isnan(double x);       int isinf(double x);     int isfinite(double x);

<stdlib.h> (memory / conversion)

void  *malloc(size_t size);
void  *calloc(size_t nmemb, size_t size);
void  *realloc(void *ptr, size_t size);
void   free(void *ptr);
int    atoi(const char *s);
long   atol(const char *s);
double atof(const char *s);
long   strtol(const char *s, char **endptr, int base);
double strtod(const char *s, char **endptr);
int    abs(int x);     long labs(long x);     long long llabs(long long x);
void   qsort(void *base, size_t n, size_t size, int (*cmp)(const void*, const void*));
void  *bsearch(const void *key, const void *base, size_t n, size_t size,
               int (*cmp)(const void*, const void*));
int    rand(void);     void srand(unsigned seed);
void   exit(int status);    void abort(void);
int    system(const char *cmd);