Wednesday, July 22, 2026

Choosing Programming Language

 ENIAC 

Used Decimal system

Initially used to find ballistic trajectory 

Team adjusted knobs and final trajectory was pushed to Punch Card 

EDVAC (1949): 




  switched to true binary 0 and 1 machine code and stored those 0s and 1s as acoustic waves inside tubes of liquid mercury 

introduced the Stored-Program Concept. The instructions to calculate a trajectory were converted into digital binary code (0s and 1s) and saved directly into the computer's memory

Assembly 

replaced raw binary instructions with short, memorable text commands called mnemonics. Instead of typing 00001011, the programmer typed ADD


Hand written 












Core Features of C
  • Procedural and Structured: Programs are organized using distinct, reusable blocks called functions.
  • Low-Level Hardware Access: Allows direct manipulation of computer memory registers and hardware addresses.
  • Pointers: Variables that store the exact memory addresses of other variables for high-speed data handling.
  • Statically Typed: All variable data types (like integers or characters) must be declared and checked before compiling.
  • Extremely Portable: Source code can be easily compiled for completely different computer architectures with minimal changes.
  • Minimalist Standard Library: Focuses on raw performance, avoiding heavy built-in features to keep the runtime footprint tiny.

New Features in C++ (On Top of C)

  • Object-Oriented Programming (OOP): Introduced Classes and Objects to group data variables and functions together into single units.
  • Encapsulation & Access Control: Added keywords (publicprivateprotected) to secure data from unauthorized modification.
  • Polymorphism (Virtual Functions): Enables a single command to behave differently based on the specific type of object executing it.
  • Inheritance: Allows a new class to automatically adopt the properties and code of an existing class, reducing duplicate work.
  • Constructors & Destructors: Automatically allocate memory when an object is created and safely clean it up when deleted, preventing memory leaks.
  • Function & Operator Overloading: Allows multiple functions to share the exact same name if they use different inputs, and lets standard symbols (like +) manipulate user-defined objects.
  • References (&): Introduced a safer, cleaner alternative to C pointers that acts as an alias for an existing variable without the risks of manual address arithmetic.
  • Standard Template Library (STL): Provided a massive, pre-built collection of ready-to-use data structures (like vectors, lists, and queues) and algorithms out of the box.

The C Compilation Process (4 Key Steps)

When you run a command like gcc main.c, the compiler executes four distinct steps behind the scenes to turn human-readable C code into a runnable binary executable file.
 [ .c Source Code ] 
         │
         ▼  (Step 1) PREPROCESSING (Expands macros, includes headers)
 [ .i Expanded Source ]
         │
         ▼  (Step 2) COMPILATION (Translates C to Assembly)
 [ .s Assembly Code ]
         │
         ▼  (Step 3) ASSEMBLY (Translates Assembly to Binary Object)
 [ .o / .obj Object Code ] ───▶ [ Linker ] ◀─── [ Pre-compiled Libraries ]
                                   │
                        (Step 4)   ▼ LINKING (Stitches blocks together)
                             [ Executable Binary ]

Step 1: Preprocessing

  • What happens: The preprocessor (cpp) cleans up the raw text of your .c source code file.
  • The actions: It strips away comments, copies the contents of header files (like #include <stdio.h>) directly into the file, and replaces macro shorthand (like #define PI 3.14) with its actual value.
  • Output: A temporary, expanded pure text file (usually ending in .i).

Step 2: Compilation

  • What happens: The compiler core (cc1) translates the high-level syntax of the preprocessed text file into low-level machine logic.
  • The actions: It analyzes syntax errors, maps data variables to hardware registries, and outputs the code using architecture-specific computer instructions.
  • Output: An assembly language text file tailored to your specific CPU (usually ending in .s).

Step 3: Assembly

  • What happens: The assembler (as) converts human-readable assembly instructions into raw machine language instructions.
  • The actions: It translates commands like MOV or ADD directly into binary operational codes (opcodes).
  • Output: An unlinked machine-code binary file called an Object File (usually ending in .o or .obj). This file cannot run yet because it contains placeholder addresses for unresolved functions.

Step 4: Linking

  • What happens: The linker (ld) stitches independent code blocks into a single, cohesive, self-contained system executable file.
  • The actions: If your program calls a standard library routine (like printf), the linker finds its pre-compiled binary code inside the operating system library paths and links it. It also merges multiple user-written .o files into one layout and resolves memory addresses.
  • Output: The final executable file (e.g., a.outmain, or main.exe).

What Changed in this Process for C++?

The fundamental structural stages (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Assembly $\rightarrow$Linking) remain identical in C++. However, because C++ introduces objects, classes, and function overloading, the compiler and linker had to adopt three major procedural changes on top of the standard C pipeline:

1. Name Mangling (During Compilation)

  • The Challenge: In C, every function must have a completely unique name. In C++, you can have three distinct functions all named print() as long as they accept different data inputs (Function Overloading).
  • The Change: To prevent the assembler and linker from getting confused by matching names, the C++ compiler automatically rewrites function names behind the scenes. A function like print(int x) is mangled into something unique like _Z5printi. This ensures the linker can uniquely match function calls to their exact binary definitions.

2. VTable Generation (During Compilation)

  • The Challenge: C++ supports runtime polymorphism, meaning a single function call to a base class might need to execute entirely different code depending on which inherited object subclass is active at runtime.
  • The Change: The C++ compiler generates a hidden lookup array called a Virtual Table (VTable) for classes containing virtual functions. Instead of hardcoding a direct memory address during compilation, it emits instructions telling the processor to look up the target address inside the VTable at execution time.

3. Object Construction & Destructor Injections (During Compilation)

  • The Challenge: C++ objects require precise memory initialization upon creation and automatic memory cleanup when they fall out of scope.
  • The Change: The compiler steps through your functions and silently injects low-level constructor and destructor instructions directly into the assembly pipeline. It ensures that memory allocations, pointer tracking, and variable initialization happen automatically without requiring explicit manual code updates from the developer.

Because Java was designed to solve the problem of "Write Once, Run Anywhere" (WORA), it introduced a dual-stage execution model. It sits completely on top of a runtime engine written in C++, which handles the heavy lifting of interacting with the physical operating system.
Here is the exact breakdown of how this pipeline operates under the hood:
1. The Compilation Phase (Human to Bytecode)
  • What Happens: When a developer writes code in a .java file and compiles it (using javac), the compiler does not generate machine code or assembly for a real CPU.
  • The Output: It outputs a .class file containing Bytecode. Bytecode is a highly optimized set of instructions designed for a hypothetical, universal computer—the JVM.
2. The JVM: Built on C++
  • The Layer: The standard JVM (Oracle’s HotSpot) is a massive software application written primarily in C++ (along with some low-level Assembly).
  • The Subsystem: Because it is built in C++, it has direct access to OS system calls, memory management, and threads. The JVM acts as a buffer shield between your Java code and the operating system.
3. The Execution Phase (Bytecode to Assembly)
When you run a Java application, the C++ engine of the JVM processes the bytecode using two distinct execution strategies:
[ .class Bytecode ] 
         │
         ▼
 ┌─────────────── JVM (Built in C++) ────────────────┐
 │                                                   │
 │ ──▶ [ Interpreter ] ──▶ Translates line-by-line   │
 │                                                   │
 │ ──▶ [ JIT Compiler ] ─▶ Translates hot loops      │
 │                         directly to Native Asm    │
 └───────────────────────────────────────────────────┘
         │
         ▼
 [ Native OS / CPU Assembly ]
  • The Interpreter: The JVM reads the bytecode instructions line-by-line and translates them into corresponding C++ runtime functions, which then execute on the OS. This gets the program running instantly but is relatively slow.
  • The JIT (Just-In-Time) Compiler: To speed things up, the JVM monitors the running code. If it finds a section of bytecode that is executed repeatedly (a "hot spot"), the JIT compiler instantly compiles that bytecode block directly into native CPU assembly code in memory, completely bypassing interpretation for subsequent loops.

Why Was This Shift Away From Native C++ Necessary?
MetricC++ StrategyJava / JVM Strategy
TargetCompiles down to a specific OS/CPU architecture.Compiles down to universal intermediate Bytecode.
PortabilityMust recompile the entire codebase for every single platform.The same .class file runs unmodified on any machine with a JVM.
MemoryManual memory allocation (mallocnewdelete).Automatic Garbage Collection handled by the C++ engine.
SafetyCrash-prone if pointers access illegal memory spaces.Sandboxed environment prevents direct malicious memory corruption.
1. Python is Built on C, Not C++
The standard, official version of Python that everyone downloads from Python.org is called CPython. As the name suggests, the entire Python executable, its runtime environment, and its core libraries are written in pure C, not C++. [123]
(Note: There are alternative versions of Python like PyPy, or Jython which is written in Java, but the standard engine is completely C-based). [12]
2. Python Does Not Convert Code to Assembly
Unlike a C++ compiler, the standard Python interpreter never converts your Python code into CPU assembly language or machine code instructions. [12]
Instead, the process looks like this:
[ .py Source Code ]
         │
         ▼  (Step 1: Automated Compilation)
[ .pyc Bytecode ]  ──▶ Stored in __pycache__ folder
         │
         ▼  (Step 2: Interpretation Loop)
 ┌─────────────── CPython Engine (Written in C) ──────────────┐
 │                                                            │
 │  Reads Bytecode instructions one-by-one                   │
 │                                                            │
 │  [ Bytecode: BINARY_ADD ] ──▶ Evaluates via C functions    │
 │                                                            │
 └────────────────────────────────────────────────────────────┘
         │
         ▼
 [ Directly Triggers Pre-Compiled C Executable Logic on CPU ]
Step 1: The Hidden Compilation (Source to Bytecode)
When you run a Python script, it doesn't immediately read the text line-by-line. First, Python’s internal C-compiler parses your entire .py file and translates it into an intermediate low-level language called Bytecode (compiled .pyc files found in your __pycache__ directory). [12]
Step 2: The Virtual Machine Loop (No Assembly Needed)
This bytecode is handed over to the Python Virtual Machine (PVM). The PVM is just a massive loop written in C. It reads the bytecode instructions one at a time: [12]
  • If your bytecode says BINARY_ADD, the PVM does not generate an assembly ADD instruction for your computer chip.
  • Instead, the PVM calls a pre-compiled C function (like PyNumber_Add()) that has already been turned into machine code when Python itself was installed on your computer.
Summary: Why This Matters
Because Python relies on a C-runtime engine to evaluate instructions on the fly rather than translating your code directly into native CPU assembly, it achieves incredible cross-platform flexibility. However, this extra layer of runtime interpretation is also the exact reason why Python runs significantly slower than pure compiled languages like C or C++. [123]

No comments:

Post a Comment

Choosing Programming Language

 ENIAC  Used Decimal system Initially used to find ballistic trajectory  Team adjusted knobs and final trajectory was pushed to Punch Card  ...