The Short Answer: C, C++, and the Wiring Framework

When beginners ask, "what language does Arduino use?", the most accurate answer is a nuanced one: Arduino uses a specialized dialect of C and C++ built upon the Wiring framework. While the Arduino IDE allows you to write code in files ending with the .ino extension, this is merely a convenience for the user. Under the hood, the Arduino build system translates your sketch into standard C++ code, compiles it using the GCC toolchain, and flashes the resulting machine code to the microcontroller.

Understanding this distinction is critical for makers transitioning from simple blink sketches to complex, memory-constrained embedded systems in 2026. The Arduino ecosystem abstracts away the harsh realities of hardware registers, but knowing what happens behind the curtain allows you to optimize memory, avoid heap fragmentation, and integrate third-party C libraries seamlessly.

The Hidden main.cpp: How setup() and loop() Actually Work

In standard C or C++ programming, every executable program must have a main() function—the entry point where execution begins. However, Arduino sketches only require two functions: setup() and loop(). Where does the main() function go?

The Arduino core library contains a hidden main.cpp file that is automatically linked to your sketch during compilation. According to the official Arduino Language Reference, the core framework handles hardware initialization before your code ever runs. Here is the exact C++ code that the compiler injects behind the scenes for standard AVR boards:

#include <Arduino.h>

int main(void) {
    init(); // Configures timers, ADC, and UART hardware
    setup(); // Calls your user-defined setup function
    
    for (;;) { // Infinite loop
        loop(); // Calls your user-defined loop function
        if (serialEventRun) serialEventRun(); // Handles serial buffers
    }
    
    return 0;
}

This architectural decision was made to lower the barrier to entry. By hiding the infinite for (;;) loop and hardware initialization, beginners can focus purely on logic. However, advanced users can bypass this by writing their own main() function directly in a .cpp file, taking total control of the execution lifecycle and saving precious clock cycles.

The Compilation Pipeline: From .ino to Machine Code

To truly understand what language Arduino uses, you must understand how the IDE processes your text. When you click "Upload", a multi-stage pipeline executes:

  1. Sketch Preprocessing: The IDE concatenates all .ino tabs into a single file. It automatically generates function prototypes (declarations) for any custom functions you wrote, appending them to the top of the file. This prevents the "function not declared in this scope" errors common in standard C++.
  2. File Conversion: The combined file is renamed with a .cpp extension and moved to a temporary build directory.
  3. Compilation (GCC): The avr-gcc compiler (for 8-bit AVR chips like the ATmega328P) or arm-none-eabi-gcc (for 32-bit ARM chips like the RP2040) compiles the C++ code into object files (.o). The GCC AVR Wiki details the specific optimization flags used, such as -Os (optimize for size) and -fno-exceptions.
  4. Linking: The linker combines your object files with the pre-compiled Arduino core libraries (core.a) to create an ELF (Executable and Linkable Format) file.
  5. Hex Conversion: The ELF file is stripped of debugging symbols and converted into an Intel HEX file (.hex), which is a text-based representation of the raw binary machine code.
  6. Flashing: A tool like avrdude or bossac pushes the .hex file to the microcontroller's flash memory via USB, UART, or SPI.

Standard C++ vs. Arduino C++: The Missing Features

Because microcontrollers operate with severe memory constraints, the Arduino implementation of C++ deliberately disables several standard features. If you are porting standard desktop C++ code to an Arduino, you will encounter these limitations immediately.

Feature Standard Desktop C++ Arduino C++ (AVR / 8-bit) Why It Is Disabled / Modified
Exceptions (try/catch) Fully Supported Disabled (-fno-exceptions) Exception handling adds massive overhead to binary size and requires complex stack unwinding, which bloats limited Flash memory.
RTTI (Runtime Type Info) Fully Supported Disabled (-fno-rtti) Storing type metadata consumes precious RAM and Flash. dynamic_cast and typeid will fail to compile.
Standard Template Library (STL) Included by default Not included natively Standard std::vector or std::string rely on dynamic heap allocation, which causes catastrophic memory fragmentation on chips with only 2KB of SRAM.
Standard I/O (iostream) std::cout, std::cin Replaced by Serial.print() iostream adds tens of kilobytes to the binary. Arduino uses a lightweight, custom Serial class instead.
Dynamic Memory (new/delete) Standard practice Strongly Discouraged Using new and delete on an ATmega328P leads to heap fragmentation, eventually causing the device to crash unpredictably after hours of runtime.

The 2026 Landscape: Alternative Languages for Microcontrollers

While C and C++ remain the undisputed kings of bare-metal performance, the maker ecosystem has evolved dramatically. Depending on your hardware, you are no longer strictly bound to the Arduino C++ dialect.

1. Rust (The Memory-Safe Challenger)

Rust has made massive inroads into embedded development by 2026. Frameworks like avr-hal allow you to write strictly typed, memory-safe code for classic Arduino UNO boards, while the Rust Embedded Working Group provides the embassy framework for modern ARM Cortex-M chips like the Raspberry Pi Pico (RP2040). Rust eliminates the buffer overflows and null pointer dereferences that plague C/C++ developers, though it comes with a steeper learning curve and longer compilation times.

2. MicroPython and CircuitPython

For rapid prototyping on 32-bit boards, Python is the language of choice. MicroPython (and Adafruit's fork, CircuitPython) runs a lightweight Python 3 interpreter directly on the microcontroller. This is only viable on boards with at least 256KB of Flash and 64KB of SRAM, such as the ESP32-S3 or RP2040. You sacrifice raw execution speed and deterministic timing, but gain the ability to write and test code in seconds without waiting for C++ compilation.

3. JavaScript (Espruino)

The Espruino project allows you to program microcontrollers using JavaScript. Unlike Node.js on a PC, Espruino executes JS directly on the bare metal without an underlying operating system. It is highly popular for IoT projects where developers want to use the same language on the MCU as they do on their web front-ends.

Memory Constraints: Why Language Dictates Hardware

Your choice of programming language must align with your microcontroller's physical memory architecture. Attempting to run an interpreted language on an 8-bit AVR chip is a recipe for failure. Below is a breakdown of common maker boards and their language compatibility in 2026.

Microcontroller Board Architecture Flash / SRAM Recommended Languages
Arduino UNO R3 / Nano 8-bit AVR (ATmega328P) 32KB / 2KB Arduino C/C++, Rust (avr-hal)
Arduino Mega 2560 8-bit AVR (ATmega2560) 256KB / 8KB Arduino C/C++
Raspberry Pi Pico 32-bit ARM (RP2040) 2MB / 264KB Arduino C++, MicroPython, Rust, C SDK
ESP32-S3 DevKit 32-bit Xtensa LX7 8MB / 512KB Arduino C++, ESP-IDF (C), MicroPython

Frequently Asked Questions

Can I write pure C code in the Arduino IDE?

Yes. Because C++ is a superset of C, any valid C code will compile perfectly in the Arduino IDE. You can create files with a .c extension in your sketch folder, and the GCC compiler will process them using the C standard rather than C++. You will need to use extern "C" wrappers in your header files if you want to call these C functions from your main .ino C++ file.

Why doesn't Arduino use Java or C#?

Java and C# require a Virtual Machine (JVM or CLR) and automatic garbage collection to manage memory. Garbage collection introduces unpredictable pauses in execution (latency), which is unacceptable for real-time hardware control like reading PWM signals or managing motor encoders. Furthermore, the overhead of a VM far exceeds the memory capacity of standard microcontrollers.

Is the Arduino language proprietary?

No. The Wiring framework and the Arduino core libraries are entirely open-source, released under the LGPL and GPL licenses. The underlying compiler (GCC) is also open-source. You are never locked into the Arduino IDE; you can write Arduino C++ code in VS Code, PlatformIO, or CLion and compile it using standard command-line Makefiles.

Summary

Ultimately, what language Arduino uses depends on how deep you look. On the surface, it is a beginner-friendly scripting environment. Beneath the surface, it is a robust, highly optimized C++ framework designed to squeeze maximum performance out of minimal hardware. Whether you stick to the classic Wiring framework, optimize your memory with raw C pointers, or embrace modern alternatives like Rust and MicroPython on 32-bit hardware, understanding the compilation pipeline is the first step toward mastering embedded electronics.