Freestanding vs. hosted implementations
A couple of months ago, Michael Barr wrote an article for Embedded.com entitled "Real men program in C."1 The article prompted numerous comments from readers, including a number who cited reasons to prefer C over C++. I chimed in by writing a column entitled "Poor reasons for rejecting C++" in which I explained why I disagreed with some of those comments.2 That, in turn, provoked another flurry of comments. Many of those comments affirmed the wisdom of my analysis, thank you. Others raised interesting issues that I will try to address in this and future columns.
Some readers took exception to my statement that, "I know of no place where the C++ language performs dynamic allocation or recursion behind the scenes." One reader wrote that, "The flexible nature of common data types such as the C++ vector and string classes would seem to completely rely on dynamic allocation, just as the whole STL library. I can't quite see how you could implement things like the string + operator, vector push_back member function, etc. ... without a heap ..."
Arguably, I could have been more explicit that I was talking only about the C++ language itself and not its accompanying library. I did elaborate that, "Indeed, your code might call a function that uses dynamic allocation or recursion, but this is no more a problem in C++ than in C," but I guess I wasn't explicit enough.
I think embedded programmers should learn to think of the C and C++ programming languages as distinct from their accompanying standard libraries. Although I'm not prepared to say embedded programmers should view all languages this way, it's probably an appropriate way to view statically-typed, compiled languages, which include C and C++, as well as others such as Ada. Most compilers come with a small collection of mysteriously-named functions that support operations such as program startup, program shutdown, and floating point arithmetic, but such functions are not really part of the library as defined by the language standards. Rather, such functions are just artifacts of the compiler's code generation strategy.
The C Standard formalizes a separation between the language and the library by distinguishing between hosted and freestanding implementations. Informally, a hosted implementation is a C translation and execution environment running under an operating system with full support for the language and library. A freestanding implementation is a C translation and execution environment with nearly full language support but essentially no support for the standard library's runtime components--an environment not uncommon among low-end embedded systems.