The Short Answer: It is C++ (With a C-Style Wrapper)

When beginners and seasoned embedded engineers alike ask, "is Arduino C or C" (meaning C++), the answer requires looking beneath the simplified surface of the Arduino IDE. The short answer is that Arduino sketches are compiled as C++. However, the ecosystem is built on a foundation of C-style procedural programming, heavily abstracting hardware registers behind C++ classes and C-compatible functions.

As of 2026, the Arduino ecosystem has expanded far beyond the original 8-bit AVR microcontrollers. With the introduction of ARM Cortex-M4 boards like the Uno R4 Minima and the Nano 33 IoT, the underlying toolchains now leverage modern C++17 standards via arm-none-eabi-gcc. Yet, the community's coding style remains a hybrid. This roundup synthesizes expert insights, toolchains, and community resources to help you master the language behind the microcontroller.

Deconstructing the IDE: How .ino Files Become C++

To understand the language, you must understand the build pipeline. When you click "Verify" or "Upload" in the Arduino IDE (or run arduino-cli compile), the system does not pass your .ino file directly to the compiler. Instead, it performs a preprocessing step:

  1. File Concatenation: All .ino tabs in your sketch folder are merged into a single temporary file.
  2. Header Injection: The line #include <Arduino.h> is automatically prepended to the top of the file. This header is the bridge, pulling in standard C libraries (stdlib.h, string.h) and C++ hardware abstraction classes (HardwareSerial, Stream).
  3. Prototype Generation: The IDE scans your code and automatically generates function prototypes for any custom functions you have written, allowing you to define functions below setup() and loop() without forward declarations—a convenience not natively supported in standard C or C++.
  4. Main Function Injection: A hidden main.cpp file is linked, which initializes the hardware (timers, ADC, UART) and calls your setup() once, followed by an infinite while(1) loop that calls your loop().

Because the final output is passed to avr-gcc (for AVR boards) or arm-none-eabi-gcc (for ARM boards) with C++ flags enabled, you have full access to object-oriented programming (OOP), templates, and the Standard Template Library (STL), provided you manage memory correctly.

Community Consensus: C vs. C++ Paradigms on MCUs

The maker community is divided on how to structure firmware. Below is a comparison of the two dominant paradigms discussed across forums like EEVblog and the official Arduino Discord.

Feature C-Style Procedural (The 'Classic' Way) C++ Object-Oriented (The Modern Way)
State Management Global variables or struct passed by pointer. Private class members encapsulated in objects.
Hardware Abstraction Direct register manipulation (e.g., PORTB |= (1 << 5)). Virtual classes and interfaces (e.g., inheriting from Print).
Memory Overhead Minimal. No hidden pointers or v-tables. Virtual functions add v-table overhead (Flash & SRAM cost).
Code Reusability Copy-pasting or using complex macro definitions. C++ Templates and inheritance for type-safe reuse.
Best For ATtiny85, ATmega328P (strict 2KB SRAM limits). ESP32, Arduino Uno R4 (Renesas RA4M1), Teensy 4.1.

2026 Community Resource Roundup

To transition from writing basic sketches to engineering robust C++ firmware, the community relies on a specific set of tools and repositories. Here are the top resources curated by embedded systems professionals.

1. The Core Framework Repositories

Reading the source code of the core libraries is the fastest way to understand how C and C++ interact on the hardware. The ArduinoCore-avr GitHub repository is the definitive resource for 8-bit AVR boards. By exploring the cores/arduino directory, you can see exactly how C++ classes like HardwareSerial wrap around C-style Interrupt Service Routines (ISRs) and volatile register buffers.

2. Professional Toolchains: PlatformIO

While the Arduino IDE 2.x has improved significantly with its language server, professional developers overwhelmingly prefer PlatformIO. The PlatformIO official documentation details how to configure platformio.ini to enforce strict C++ standards, enable link-time optimization (LTO), and integrate unit testing frameworks like Unity. PlatformIO bypasses the Arduino IDE's "magic" prototype generation, forcing you to write standard-compliant C++ headers and source files.

3. The Official Language Reference

It sounds basic, but the Arduino Language Reference remains the most accurate map of the C/C++ hybrid functions available. Pay special attention to the "Advanced I/O" and "Math" sections, which document C-macros and inline functions that compile down to single AVR assembly instructions, bypassing C++ function call overhead entirely.

Memory Management: The SRAM Reality Check

The most critical difference between writing C and C++ on microcontrollers lies in memory management. On a standard Arduino Uno R3 (ATmega328P), you are constrained to exactly 2,048 bytes of SRAM.

Expert Insight: "Using C++ new and delete on an ATmega328P is a ticking time bomb. The AVR heap does not compact. If you dynamically allocate and free memory of varying sizes using C++ objects, heap fragmentation will eventually cause new to return a null pointer, crashing the board silently. Stick to static allocation or C-style memory pools on 8-bit architectures."

Safe C++ Practices for Low-Memory MCUs

  • Avoid std::string: The standard C++ string class allocates memory on the heap. Instead, use C-style char arrays or the Arduino String class with extreme caution (pre-reserving memory using reserve()).
  • Use the F() Macro: C++ string literals are copied to SRAM at boot. Wrapping them in the F() macro forces the compiler to leave them in Flash memory, reading them byte-by-byte via the pgm_read_byte C-function.
  • Templates over Virtuals: If you need polymorphism but lack the SRAM for v-tables, use C++ Templates to resolve types at compile-time, resulting in zero runtime memory overhead.

The ARM Cortex-M4 Shift: Arduino Uno R4

The conversation around "is Arduino C or C++" shifted dramatically with the release of the Uno R4 Minima and WiFi. Powered by the Renesas RA4M1 ARM Cortex-M4 processor, these boards feature 32KB of SRAM and 256KB of Flash. This hardware leap means the strict C-style optimizations required for the ATmega328P are no longer mandatory.

On the R4, the community actively encourages the use of modern C++17 features. You can safely utilize std::vector, std::array, and even std::unique_ptr for deterministic resource management without fearing immediate heap fragmentation. Furthermore, the ARM toolchain supports hardware floating-point operations (FPU), meaning C++ math classes no longer incur the massive performance penalty associated with software-emulated floats on 8-bit AVR chips.

Summary: Choosing Your Paradigm

Ultimately, Arduino is a C++ environment dressed in C-style clothing for accessibility. If you are programming an 8-bit ATmega or ATtiny, lean into C-style procedural code, direct register manipulation, and static memory allocation. If you are developing for the ESP32, Teensy, or the modern Uno R4, embrace modern C++ object-oriented design, utilizing the STL and RAII (Resource Acquisition Is Initialization) patterns to write safer, more maintainable firmware. By leveraging community toolchains like PlatformIO and studying the core repositories, you can transcend the beginner IDE and engineer professional-grade embedded systems.