Every programming language you write in must eventually become machine code before your CPU can run it. The question is when and how that translation happens — and that single difference changes everything about how a language feels, performs, and gets deployed.

What Does a Computer Actually Understand?

Your CPU understands exactly one thing: machine code — raw binary instructions like 10110000 01100001. Not Python. Not JavaScript. Not C++. Every language you write must, at some point, become machine code. The compiled vs interpreted distinction is just about when that translation happens.

Compiled Languages — Translate First, Run Later

A compiler reads your entire source code and translates it into machine code before you run it. The output is a standalone executable — a binary the OS can run directly, no translator needed at runtime.

Source Code (.c / .cpp)
Compiler
Machine Code (.exe / binary)
CPU runs it directly
hello.c
// hello.c
#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

// Compile:  gcc hello.c -o hello
// Run:      ./hello

When you run gcc hello.c -o hello, the compiler reads your whole file, checks for errors, optimizes the logic, and produces a binary. That binary runs at full CPU speed — nothing sitting in between translating at runtime.

What the compiler does behind the scenes: Lexing → Parsing → Semantic Analysis → Optimization → Code Generation. All that work happens once upfront so every future run is as fast as possible.

Languages That Are Compiled

C C++ Go Rust Fortran

Interpreted Languages — Translate as You Go

An interpreter reads your source code line by line and executes it on the fly — no separate compilation step, no binary output. The interpreter itself is the runtime.

Source Code (.py / .js)
Interpreter (line by line)
Executed immediately
hello.py
# hello.py
print("Hello, World!")

# Run it:  python hello.py

When you run python hello.py, Python reads your file, processes each statement, and executes it. There's no .exe produced — because the interpreter handles everything at runtime.

Runtime errors show up differently: A bug on line 50 won't be caught until execution actually reaches line 50 — even if lines 1–49 ran fine. Compiled languages catch many of these before you even run the program.

Languages That Are Interpreted

Python Ruby PHP Bash JavaScript (traditionally)

The Modern Reality — It's Not Black and White

Most modern languages live somewhere in the middle. The compiled/interpreted line has blurred significantly. Here are the two big hybrid models:

The Bytecode Model — Java, Python, C#

Source code is compiled to an intermediate format called bytecode — not raw machine code, but a compact platform-neutral representation. At runtime, a Virtual Machine (JVM for Java, CPython for Python, CLR for C#) executes the bytecode.

Source Code
Bytecode (.pyc / .class)
Virtual Machine
CPU

This is why Java is "write once, run anywhere." The same .class file runs on any machine with a JVM installed — no recompiling for each platform.

JIT Compilation — JavaScript V8, Java HotSpot, PyPy

Just-In-Time compilation is how modern runtimes get near-compiled performance from interpreted code. The runtime watches which parts of your code run most frequently ("hot paths") and compiles those specific parts to native machine code on the fly.

This is why modern JavaScript in Chrome's V8 engine is shockingly fast — V8 JITs your hot loops into machine code at runtime. It's why Node.js can handle serious backend workloads.

Side-by-Side Comparison

Feature Compiled Interpreted
Translation timeBefore runtime (build step)At runtime (line by line)
Execution speedFast (direct machine code)Slower (interpreter overhead)
Error detectionAt compile timeAt runtime (when that line runs)
PortabilityOS/arch-specific binaryCross-platform with interpreter
Dev speedSlower (compile → run cycle)Faster (run immediately)
Output fileStandalone executableNo separate output
ExamplesC, C++, Go, RustPython, Ruby, PHP, Bash

Common Myths, Busted

Myth: Python is slow because it's interpreted. CPython is slower for CPU-bound tasks — but NumPy and SciPy call compiled C code under the hood, and PyPy JITs Python to near-C speeds.
Reality: It depends on what you're doing. For data science and ML, Python's ecosystem beats everything. Slow language, fast libraries.
Myth: JavaScript is slow because it's interpreted. This was true in 2005. V8's JIT compiler makes modern JS extremely fast — often benchmarking close to Go for I/O workloads.
Reality: Modern JS is JIT-compiled. Node.js handles millions of requests per second. "Interpreted = slow" hasn't been accurate for over a decade.

Which Should You Use?

Compiled (C, Go, Rust) — when raw performance matters: OS kernels, game engines, embedded systems, CLI tools where startup time counts.

Interpreted/bytecode (Python, JavaScript, Java) — web development, data science, scripting, prototyping, or any domain where developer productivity and ecosystem outweigh squeezing out milliseconds.

Most working developers use both — Python for data pipelines, Go for the API server, JavaScript for the frontend.

Quick Check: Java compiles to bytecode that runs on the JVM. Is Java compiled or interpreted? The answer: both — and now you know exactly why. Try writing the same loop in Python and C, time both, then try PyPy and watch the gap close.

Enjoyed this? Next up: How Memory Management Works in Python vs C — the hidden layer that explains even more of what happens when your code runs.