Recent from talks
Nothing was collected or created yet.
Embedded C++
View on WikipediaEmbedded C++ (EC++) is a dialect of the C++ programming language for embedded systems. It was defined by an industry group led by major Japanese central processing unit (CPU) manufacturers, including NEC, Hitachi, Fujitsu, and Toshiba, to address the shortcomings of C++ for embedded applications. The goal of the effort[1] is to preserve the most useful object-oriented features of the C++ language yet minimize code size while maximizing execution efficiency and making compiler construction simpler. The official website states the goal as "to provide embedded systems programmers with a subset of C++ that is easy for the average C programmer to understand and use".[2]
Differences from C++
[edit]Embedded C++ excludes some features of C++.
| Feature | ISO/ANSI C C++ | Embedded C++ |
|---|---|---|
| Exception handling | ||
| Multiple inheritance | ||
mutable, a storage class specifier
|
||
| Namespaces | ||
| Templates | ||
Run-time type information (typeid)
|
||
| Style casts ( static_cast, dynamic_cast, reinterpret_cast, and const_cast)
|
||
| Virtual base classes |
Some compilers, such as those from Green Hills and IAR Systems, allow certain features of ISO/ANSI C++ to be enabled in Embedded C++. IAR Systems calls this "Extended Embedded C++".[3]
Compilation
[edit]An EC++ program can be compiled with any C++ compiler. But, a compiler specific to EC++ may have an easier time doing optimization.
Compilers specific to EC++ are provided by companies such as:
- IAR Systems[4]
- Freescale Semiconductor, (spin-off from Motorola in 2004 who had acquired Metrowerks in 1999)
- Tasking Software,[5] part of Altium Limited
- Green Hills Software[6]
Criticism
[edit]The language has had a poor reception with many expert C++ programmers. In particular, Bjarne Stroustrup says, "To the best of my knowledge EC++ is dead (2004), and if it isn't it ought to be."[7] In fact, the official English EC++ website has not been updated since 2002. Nevertheless, a restricted subset of C++ (based on Embedded C++) has been adopted by Apple Inc. as the exclusive programming language to create all I/O Kit device drivers for Apple's macOS, iPadOS and iOS operating systems of the popular Macintosh, iPhone, and iPad products.[8] Apple engineers felt the exceptions, multiple inheritance, templates, and runtime type information features of standard C++ were either insufficient or not efficient enough for use in a high-performance, multithreaded kernel.[9]
References
[edit]- ^ "EC++ Rationale".
- ^ EC++ Questions and Answers
- ^ "Embedded and Extended Embedded C++". Archived from the original on 21 May 2013. Retrieved 9 December 2012.
- ^ "IAR Systems - Compilers and debuggers". IAR Systems website. Archived from the original on 2015-01-05. Retrieved 2011-02-21.
- ^ "Embedded C++ compiler technology". Tasking website. Archived from the original on 2009-01-01.
- ^ "Green Hills Optimizing C/C++/EC++ Compilers". Green Hills Software website. Archived from the original on 2008-10-25.
- ^ "What do you think of EC++?". Bjarne Stroustrup's FAQ.
- ^ "What is Mac OS X?". Amit Singh. Archived from the original on 2019-04-19. Retrieved 2015-03-04.
- ^ "The libkern C++ Runtime". IOKit Device Driver Design Guidelines.
External links
[edit]- Official website
- Background and Objectives of the Embedded C++ Specification Development
- Embedded C++ Yields Faster Smaller Code, John Carbone (Embedded.com), June 19, 1998
- Building Bare-Metal ARM Systems with GNU: Part 1 - Getting Started, Miro Samek, Quantum Leaps, June 26, 2007
- Technical Report on C++ Performance, by WG 21 of ISO Subcommittee SC 22
Embedded C++
View on GrokipediaOverview
Definition and Purpose
Embedded C++ is defined as a restricted subset of the ISO C++ standard, specifically tailored for programming resource-constrained embedded systems such as microcontrollers. This subset maintains core object-oriented features like classes and inheritance while excluding advanced elements that introduce runtime overhead, ensuring compatibility with hardware limitations including limited RAM, often under 64 KB, and the absence of operating system support.[1][4] The primary purpose of Embedded C++ is to enable efficient object-oriented programming in environments where predictability and minimal resource usage are paramount, such as real-time systems. By focusing on static memory allocation and compile-time resolutions, it avoids dynamic memory management mechanisms like exceptions and runtime type information, which can lead to unpredictable execution times and increased code size in full C++. This approach promotes ROMability—allowing code to be stored directly in read-only memory—and deterministic behavior essential for safety-critical applications.[1][5][4] Originating in the 1990s from the needs of embedded developers facing the overhead of full C++ on 32-bit RISC microcontrollers, Embedded C++ contrasts sharply with standard C++'s general-purpose design by prioritizing simplicity, portability, and efficiency over comprehensive library support and flexibility. Guidelines like MISRA C++ have built upon this foundation to further enforce reliability in industrial contexts.[1]Historical Context
The development of Embedded C++ traces its roots to the evolution of the C++ programming language, which was initially conceived in 1979 by Bjarne Stroustrup at Bell Labs as an extension of C to support object-oriented programming while maintaining low-level control.[6] By the late 1980s and early 1990s, as C++ gained traction in general-purpose computing, embedded systems developers faced challenges with its full feature set, including runtime overhead from exceptions and runtime type information, prompting interest in a lighter subset tailored for resource-constrained environments like microcontrollers.[7] This motivation culminated in the formation of the Embedded C++ (EC++) technical committee in late 1995, led by major Japanese electronics firms such as Hitachi, NEC, and Fujitsu and chaired by Hiroshi Monden of NEC Corporation. The committee released the first EC++ specification (version WP-AM-003) in October 1999 as a restricted dialect of C++98 (ISO/IEC 14882:1998) designed for embedded applications. The specification emphasized ROMability, predictability, and reduced code size, addressing the needs of real-time systems without normative status but serving as a foundational guideline.[8][3] By 2025, Embedded C++ has seen increasing acceptance in IoT and edge computing, where tools like GCC and Clang support subsets of C++20—including modules and concepts—for efficient, secure code generation in resource-limited devices.[9]Language Subsets and Features
Excluded C++ Features
Embedded C++ subsets deliberately exclude several advanced C++ features to prioritize minimal code size, predictable execution, and compatibility with resource-limited hardware, such as microcontrollers with constrained ROM and no operating system support. These omissions focus on elements that introduce runtime costs, metadata requirements, or complexity unsuitable for embedded environments, where program footprints must often fit within tens of kilobytes of flash memory. The rationale emphasizes avoiding features that do not align with the deterministic and efficient needs of embedded design.[1] Exception handling mechanisms, including try-catch blocks and throw statements, are comprehensively excluded due to their impact on execution timing and memory usage. The stack unwinding process during exception propagation creates non-deterministic delays that are difficult to predict, while the supporting infrastructure increases overall code size. In embedded systems, where real-time responsiveness is essential, these characteristics render exceptions impractical.[1] Runtime Type Information (RTTI), encompassing operators like dynamic_cast and typeid, is omitted to eliminate the storage overhead of type metadata embedded in the binary. This feature provides no significant value in straightforward embedded applications, yet it consistently enlarges program size, making it incompatible with tight memory budgets.[1] Templates, particularly their full specialization and instantiation capabilities, are restricted or avoided to prevent code bloat from generating duplicated function and class instances for each type used. Such expansion can rapidly consume limited ROM space in devices with capacities as low as 32 KB, complicating deployment on low-end microcontrollers.[1] Multiple inheritance is prohibited, with single inheritance or composition recommended as alternatives, owing to the intricate class hierarchies it fosters, which even experienced developers find challenging to manage and debug. This exclusion extends to virtual inheritance and selective avoidance of virtual function tables in scenarios involving polymorphic designs that could amplify overhead.[1] Additional omissions include the mutable specifier, which complicates read-only memory (ROM) placement by allowing modifications to supposedly constant objects, and namespaces, which are unnecessary in scoped environments where naming conflicts rarely arise. Standard Template Library (STL) components reliant on dynamic memory, such as containers, are likewise excluded to preserve strict resource control. Embedded C++ subsets, such as those aligned with ISO/IEC TR 18015, emphasize Plain Old Data (POD) types to ensure compatibility with direct memory access and absence of implicit constructor or destructor overhead.[10]Retained and Modified Elements
In Embedded C++, core object-oriented features of C++ are retained to enable abstraction and modularity while adhering to the resource constraints of embedded systems. Single inheritance is preserved, allowing derived classes to extend base classes without the complexity of multiple inheritance, which supports efficient memory layout and predictable performance overheads typically limited to a single pointer per object.[1] Polymorphism through virtual functions is allowed but should be used judiciously to minimize runtime dispatch costs via vtables.[1] Classes and objects facilitate encapsulation by bundling data and methods, with no additional space overhead beyond data members when non-virtual, enabling clean interfaces for hardware abstraction in embedded contexts.[1] Inline functions are fully supported to eliminate call overheads and aid compiler optimizations in performance-critical code.[1] Modifications to these features ensure lightweight and deterministic execution suitable for embedded environments. Constructors and destructors are required to be non-virtual and designed to be lightweight, avoiding dynamic memory allocations to prevent unpredictable timing, while still supporting initialization of objects like hardware registers.[1] Static member functions are preferred over dynamic ones for operations that do not require instance state, as they incur no per-object overhead and can be stored in read-only memory if constant.[1] Operator overloading is supported for essential cases, such as assignment (=) and pointer dereference (->), to maintain code readability without introducing unnecessary complexity or hidden conversions.[1] New and delete operators are retained but should be used sparingly to avoid heap fragmentation, non-determinism, and the need for a memory manager in systems lacking one; they are specified as no-throw due to the exclusion of exceptions.[1] Key concepts in Embedded C++ emphasize resource efficiency and predictability. Resource Acquisition Is Initialization (RAII) is promoted using constructors and destructors for automatic resource management, ensuring deterministic behavior in real-time systems.[1] The use ofconst is encouraged to enable compile-time evaluation and read-only memory placement, reducing runtime computations and enhancing optimization opportunities without any execution overhead.[1] Compatibility with C-style code is maintained to facilitate porting legacy embedded applications, with C++ features like classes adding no performance penalty over C structs when used appropriately.[1]
Specific elements such as the bool type, references, and function overloading are explicitly allowed to improve type safety and code expressiveness. The bool type is required for conditional expressions and logical operations to avoid implicit conversions that could lead to errors.[1] References provide efficient pass-by-reference semantics with no overhead beyond pointers, supporting safe and optimized function parameters.[1] Function overloading is permitted as long as parameter types are compatible, resolved entirely at compile time with no runtime cost.[1] To ensure deterministic behavior, practices ban triggers of undefined behavior, such as strict aliasing violations through overlapping object representations or pointer arithmetic beyond array bounds.[1] These retentions contrast with excluded features like multiple inheritance, which are omitted to avoid the indirection and complexity that could compromise embedded predictability.[1]
Embedded C++ also retains a limited set of non-templated, freestanding libraries, including basic string handling (Standardization and Guidelines
ISO/IEC Technical Report 18015
The ISO/IEC Technical Report 18015:2006, published on February 15, 2006, as a Type 2 technical report by the ISO/IEC JTC1/SC22/WG21 subgroup, addresses C++ performance characteristics with a dedicated emphasis on embedded systems applications. It provides guidelines for an embedded profile of the C++98 standard (ISO/IEC 14882:1998), tailored for resource-limited environments such as automotive controls, smart cards, and real-time systems. The report's rationale centers on achieving ROMability—ensuring code can reside in read-only memory—alongside predictable execution times and reduced overhead to counter misconceptions about C++'s suitability for embedded programming. Informative rather than normative, it offers programming guidelines to enable efficient, portable C++ usage in these domains without compromising determinism.[10][12] The document's structure includes sections on language features, libraries, and embedded-specific considerations, followed by annexes offering practical implementation advice. It discusses performance implications of various C++ features, recommending avoidance of those with high overhead in embedded contexts, such as exceptions (due to non-deterministic overhead in real-time scenarios), run-time type information (RTTI) for its space and complexity costs, multiple inheritance to avoid performance penalties, dynamic memory allocation for timing unpredictability, and unrestricted use of templates or virtual functions that risk code bloat. Justifications prioritize minimal runtime and memory footprints, noting that optimized C++ maintains strengths like object-oriented design while aligning with embedded constraints. It includes example code snippets to illustrate efficient patterns, such as compile-time template computations for a factorial:template <int N>
class Factorial {
public:
static const int value = N * Factorial<N-1>::value;
};
template <>
class Factorial<0> {
public:
static const int value = 1;
};
template <int N>
class Factorial {
public:
static const int value = N * Factorial<N-1>::value;
};
template <>
class Factorial<0> {
public:
static const int value = 1;
};
<hardware> interface, replacing C-style <iohw.h> for portability. Annex C details migration from C, recommending idioms like the pointer-to-implementation (PIMPL) pattern to hide details and reduce coupling, while Annex D presents performance metrics, including benchmarks like the Stepanov abstraction penalty test, demonstrating significant reductions in code size and execution time through compiler optimizations compared to unoptimized full C++ usage.[10]
TR 18015 significantly influenced early 21st-century embedded C++ implementations, serving as a reference for compiler vendors such as Green Hills Software and IAR Systems to develop compliant modes that supported the recommended profile for pre-C++11 projects. Its guidelines facilitated adoption in safety-critical domains by quantifying performance trade-offs and promoting verifiable efficiency, though as a non-binding report, its impact was primarily through industry tools and best practices rather than mandatory conformance. The 2006 report received no post-publication updates, prompting modern embedded development to rely on updated subsets and guidelines that incorporate newer language features while preserving core principles of efficiency.[10][13]
MISRA C++ Guidelines
The MISRA C++ guidelines, developed by the Motor Industry Software Reliability Association (MISRA), provide a set of rules and directives for using C++ in safety-critical and embedded systems to promote reliability, portability, and maintainability.[14] The initial edition, MISRA C++:2008, targeted the C++03 standard and included 228 rules categorized as mandatory (non-negotiable requirements), required (enforceable by static analysis tools), and advisory (recommendations for best practices).[15] These guidelines build upon the foundational MISRA C standards from 1998, adapting them to C++'s object-oriented features while restricting elements that could introduce undefined behavior or runtime errors in resource-constrained environments, drawing influence from earlier subsets like Embedded C++.[16] The 2023 edition, MISRA C++:2023, updates the guidelines for the C++17 standard, comprising 175 rules and 4 directives (179 guidelines in total), with approximately 40% of the content being new or significantly amended to address modern language features such as lambdas, auto type deduction, and constexpr.[17] This version incorporates rules from the AUTOSAR C++14 guidelines, reducing ambiguities present in the 2008 edition and re-categorizing rules into mandatory, decidable (tool-enforceable), and advisory for clearer compliance paths.[18] Key rules emphasize safety by banning undefined behaviors, such as signed integer overflow or uninitialized variables; limiting dynamic polymorphism through restrictions on virtual functions, runtime type information (RTTI), and exception handling to minimize overhead and unpredictability; requiring explicit resource management via deterministic RAII patterns without relying on implicit destructor calls in complex hierarchies; and enforcing portability checks, including avoidance of implementation-defined behaviors and compiler-specific extensions.[19] Compliance is typically verified using static analysis tools like PC-lint Plus, which report violations with rule references and support deviation management.[20] In practice, MISRA C++ guidelines are integral to certification in high-integrity domains, including automotive development for ISO 26262 compliance, where they help mitigate risks in electronic control units, and aerospace software under DO-178C, ensuring verifiable safety in flight-critical systems.[16] As of November 2025, the 2023 edition's integration with AUTOSAR C++14 has become a de facto standard for adaptive automotive platforms, complementing language subsets like ISO/IEC Technical Report 18015 by adding enforceable safety rules atop core feature restrictions.[21]Implementation in Embedded Systems
Compilation and Tooling
The compilation of Embedded C++ code typically leverages standard C++ compilers configured with specific flags to enforce the restricted feature set, ensuring compatibility with resource-constrained environments. For instance, the GNU Compiler Collection (GCC) is widely used, where flags such as-fno-exceptions and -fno-rtti disable runtime type information and exception handling to minimize overhead and code size. Cross-compilation is essential for targeting architectures like ARM Cortex-M microcontrollers, involving toolchains such as arm-none-eabi-gcc that generate binaries for bare-metal or RTOS-based systems without host dependencies.[22] Link-time optimization (LTO), enabled via -flto in GCC, performs inter-module optimizations during the linking phase, reducing executable size by eliminating redundant code and improving data flow analysis across compilation units.[23][24]
Specialized commercial toolchains dominate Embedded C++ development due to their optimizations for safety-critical and real-time applications. IAR Embedded Workbench provides a comprehensive IDE with an optimizing C++ compiler supporting subsets of C++17, including integrated build, debug, and static analysis for ARM and other embedded targets. Keil MDK (Microcontroller Development Kit) from Arm offers a robust compiler based on LLVM technology, tailored for Cortex-M devices, with features like scatter-loading for memory placement and MISRA C++ checking. Green Hills Software's MULTI IDE includes the industry's leading optimizing C++ compiler, certified for safety standards like ISO 26262, generating compact code for embedded processors while supporting advanced debugging without runtime libraries.[25] For compliance verification, static analyzers such as LDRA Tool Suite perform deep checks against MISRA C++:2008 guidelines, detecting deviations in code structure and potential runtime errors through source-level analysis.[26] Similarly, MathWorks Polyspace employs abstract interpretation to prove the absence of runtime errors in C++ code, integrating seamlessly with embedded build flows for certification in avionics and automotive domains.
Key concepts in Embedded C++ tooling revolve around efficient resource management and reliability. ROM/RAM mapping is handled via linker scripts (e.g., using GCC's ld with sections like .text for flash and .data for RAM), ensuring constants reside in read-only memory while variables are initialized appropriately to fit microcontroller constraints.[27] Interrupt-safe code generation requires compiler flags like -fno-exceptions to prevent non-deterministic behavior in interrupt service routines (ISRs), with tools generating prologue/epilogue code that avoids stack unwinding or dynamic allocations.[28] Build systems such as CMake facilitate embedded workflows through toolchain files that specify cross-compilers, linker scripts, and optimization profiles, enabling portable configurations for targets like STM32 without manual makefile maintenance.[29] Debuggers, often JTAG/SWD-based like Segger J-Link or Lauterbach TRACE32, support non-intrusive execution with minimal runtime overhead, allowing breakpoints and variable inspection in bare-metal environments without requiring a full operating system.
As of November 2025, GCC version 15 (released April 2025) and earlier versions like 14 provide robust support for C++17 subsets in embedded contexts, including structured bindings and inline variables, when configured with appropriate flags to exclude unsupported features.[30] Embedded C++ emphasizes monolithic executables with static linking only, avoiding dynamic loading to ensure predictability and reduce attack surfaces in resource-limited systems.[31] This approach, combined with the restricted language subset, yields improvements in code density over full C++ usage by eliminating unnecessary runtime support in ARM-based firmware.[32]
