What is the difference between compiled and interpreted languages?
Compiled languages translate source code into machine code before execution. Interpreted languages translate and execute it during execution. The distinction is genuinely blurrier than the textbook version suggests.
Compilation ahead of time. A compiler reads your entire program, checks it, optimises it, and emits a binary the processor runs directly. C, C++, Rust and Go work this way.
Advantages: the fastest execution, since optimisation happens once with full visibility of the program; errors caught before shipping; no runtime needed on the target machine.
Costs: a build step, and binaries tied to a platform and architecture.
Interpretation. An interpreter reads and executes the program a piece at a time. Classic shell scripting works this way.
Advantages: immediate feedback, easy portability, and runtime flexibility such as eval.
Costs: slower execution, and errors surfacing only when a line runs.
Why the distinction is not clean. This matters because most modern languages are hybrids:
Python compiles source to bytecode (the .pyc files) and then interprets that bytecode on a virtual machine. It is compiled and interpreted.
Java and C# compile to bytecode ahead of time, then a JIT (just-in-time) compiler converts hot paths to native machine code at runtime, using profiling information the ahead-of-time compiler never had. This can occasionally beat static compilation.
JavaScript engines like V8 do the same aggressively — interpreting first, then JIT-compiling frequently executed functions and deoptimising when assumptions break.
The accurate statement is that compilation and interpretation are properties of an implementation, not of a language. There are C interpreters and Python compilers.
What actually affects your work: whether there is a build step, whether type errors appear before or during execution, and whether the runtime must be installed on the target.