CCommon Pitfalls

Common Pitfalls

Most bugs beginners (and plenty of experienced programmers) hit in C fall into a fairly short, well-known list. Recognizing the pattern instantly is often enough to avoid it entirely — this page is a curated reference of the most frequent ones.

Pitfall

Example / explanation

Using = instead of ==

if (x = 5) assigns 5 to x and the condition is always true, instead of comparing -- a single missing character with no compile error

Forgetting & in scanf()

scanf("%d", x) instead of scanf("%d", &x) -- passes the value of x as an address, corrupting memory or crashing

Buffer overflows from unbounded string functions

Using gets(), strcpy(), or sprintf() without a size limit lets input longer than the buffer overwrite adjacent memory

Off-by-one errors

for (int i = 0; i <= n; i++) arr[i] reads/writes one element past the end of an n-element array

Uninitialized variables

Reading a local variable before assigning it gives an indeterminate value -- not guaranteed to be zero, and technically undefined behavior

Dangling / wild pointers

Using a pointer after free() (dangling), or one that was never initialized (wild) -- both read/write to memory you no longer own

Memory leaks

Losing the only pointer to a malloc()'d block (overwriting it, returning without freeing) means that memory can never be freed

Mismatched printf format specifiers

Using %d for a long or %s for a non-pointer silently produces garbage output or crashes -- always match the specifier to the argument type

Integer overflow

Signed overflow (e.g. INT_MAX + 1) is undefined behavior; unsigned overflow wraps around predictably but can still cause logic errors

Comparing floats with ==

Floating-point rounding means two mathematically-equal values can differ by a tiny epsilon -- compare with a tolerance instead, e.g. fabs(a - b) < 1e-9

The scariest pitfalls are the ones that 'seem to work'
Several of these (uninitialized variables, dangling pointers, signed overflow) do not reliably crash — they can silently produce plausible but wrong output, or work correctly on your machine and fail on another. Never treat "it ran without crashing" as proof of correctness; use compiler warnings and sanitizers (see the Compiler Warnings and Undefined Behavior pages) to catch these systematically.

C
#include <stdio.h>

int main(void) {
    int x = 5;

    // Pitfall: assignment instead of comparison -- this is ALWAYS true.
    if (x = 10) {
        printf("This always runs, and x is now 10!\n");
    }

    // Pitfall: comparing floats directly.
    double a = 0.1 + 0.2;
    double b = 0.3;
    if (a == b) {
        printf("Equal\n");
    } else {
        printf("Not equal -- floating point rounding!\n"); // this prints
    }

    return 0;
}