Programming Pointers
Poor reasons for rejecting C++
Dan Saks
8/20/2009 3:00 PM EDT
My colleague, Michael Barr, wrote an interesting piece earlier this month, entitled "Real men program in C."1 I won't try to summarize it--you can read it yourself. The article provoked numerous comments from readers citing reasons to prefer C over C++. I disagree with several of those comments, and I'd like to say a little in reply to each.
One reader wrote, "Just for the fun of it you might as well want to have a look at what Linus Torvalds thinks about C and C++," followed by the URL to the remark (which I've omitted intentionally).
I suppose reading what Torvalds wrote would be fun if you like reading rants. It wasn't fun for me. It's provocative but not well grounded, as explained by my friend and colleague Steve Dewhurst.2 Torvalds has made positive contributions to the computing industry, but this wasn't one of them.
Another reader wrote, "I've studied C++ but never used it professionally and, the more I study it, the less I think it appropriate for embedded use. It's not just that it is expensive in terms of resources; it encourages you to do too many risky things. It's bad enough that you can do things like dynamic allocation and recursion in C but, in C++, the language will do it without your ever realizing it, unless you know what it's doing behind the scenes..."
I have used C++ for prototyping embedded systems and consulted for others who have developed production systems in C++. The more I use it and see it used, the more convinced I am that it's preferable to C, when available.
Rather than encourage risky behavior, many of C++'s core features--such as classes, access control, constructors, destructors, references and overloading--work hand-in-hand with stricter type checking to help rein in the riskiest parts of C. While I agree that typical C++ code tends to be a bit larger and slower than comparable C, the added expense is rarely prohibitive (on the order of 10-15%). I've had little problem tuning time-critical code, such as interrupt handlers, to be as or more efficient than it would be in C.
I know of no place where the C++ language performs dynamic allocation or recursion behind the scenes. 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. In fact, C++ supports simple compile- and link-time techniques you can use to explicitly prevent using dynamic allocation, which I'll cover in an upcoming column.
Yet another reader wrote, "The only part of object orientation that is a must-have in embedded systems is private encapsulation. C supports this nicely enough with static variables declared at file scope."
While I agree with the basic sentiment of the first sentence, I wouldn't word it so strongly. I would say that the single most useful feature of C++ that's absent from C is classes with private access control. I would not call it a "must-have" feature simply because programmers do write viable embedded systems in C--without classes. However, you can write better embedded systems with classes. I wouldn't want to code without them.



DrOctavius
8/22/2009 8:52 PM EDT
Dan, I'm 100% with you.
I've been programming embedded system 20 years. I've started in assembly, then moved to C (most of our project are in C). Last year we've moved to C++, all I can say is that I will never go back.
Thanks that there are so many blind people, its like we have Ferrari and they a Fiat :)
Sign in to Reply
Sundar Srinivasan
8/22/2009 8:59 PM EDT
I agree with you, Dan. I have been programming in C and C++ and when I sit to code in C, I am still thinking in terms of objects. Object oriented modeling and programming in C++ are just great experiences. But many of the processors come instantly with a highly optimized C compiler. And few others come with C++ compiler which are not really optimized.
http://sunnyeves.blogspot.com/
Sign in to Reply
DutchUncle
2/28/2011 9:21 AM EST
The key line here: "...thinking in terms of objects." Many of the things in OO languages are about ways of thinking, assisted by ways of notation. We used to do many of the same things in Fortran - just not as neatly.
Sign in to Reply
Troy Teague
8/22/2009 11:43 PM EDT
I taught myself C++ in college (early 90's), and I remember having concerns about similar remarks back then: "C++ has too much overhead..." (usually alluding to virtual methods, like a virtual table was a process killer), "you can't write device-level code in C++..." (I've written endless device drivers in C++ for 16-bit and 32-bit windows, linux, BSD, sco unix, lynx os, etc.), "object-oriented programming is just a fad...". I ignored all of these statements primarily because I was already hooked on OOD and OOP. But perhaps one of my favorite professors said it best when I asked his opinion. "C++ allows you to solve a larger problem domain. If it runs slower, get a faster computer. They used to tell me not to use microprocessors in my embedded systems earlier in my career because microprocessors were an 'unproven technology'." (yeah, he had some experiences that pre-dated microprocessors...) Of course, there are situations that may warrant not using a C++ compiler, but make sure those reasons are technically legitimate.
So, should you use C++? Or C? Or something else?
It depends... (another common answer from yet another professor I had)
(i.e. it depends on what you are doing, project requirements, technical requirements, etc.)
Choose wisely. Don't let emotion play a role in what you should use. You will have enough headaches during the project without suffering along with the wrong tools.
Sign in to Reply
DaleShpak
8/23/2009 10:32 AM EDT
More agreement with Dan. C++ has a lot of features that support better software design. When using C++ you can use only the features that you need and avoid those that would make your app slow or bloated. For example, just using C++'s classes and type checking results in better code without bloat.
Sign in to Reply
fish-gate
8/24/2009 12:19 PM EDT
Agreed. I've been a firmware engineer for over 10 years now, and I've written low-level drivers in both languages. I have equal experience in both languages. I will always choose C++ if I can, because from my experience, it seems to to be more flexable, maintainable, portable, and reusable.
Sign in to Reply
maxlem
8/24/2009 1:05 PM EDT
The time to market advantage you can gain from a PROPER Object-Oriented architecture far overweights the small performance penalty you pay. I is a TERRIBLE mistake to choose an archaic programming paradigm in order to gain 10-15% performance. Heck, I'm using C++ for Atmel 8-bit AVR MCUs, and the code is so much more expressive and more pleasant to develop.
The problem with C++ is resistance to change from C dinosaurs.
Don't flush C++ for performance, grow-up technically and use a profiler to find bottlenecks.
Also, C++ is a language, using it without proper Object-Orientation culture is like playing european football with an american football : very frustrating.
Sign in to Reply
ablakok
8/24/2009 11:33 PM EDT
I've been programming desktop applications in C++ for several years, and I am a big proponent of good object oriented design. So when I started doing embedded programming a couple of years ago I naturally started using C++. I translated my latest project into C, mainly to see how much better it did with code size. It reduced it, although that was not crucial. But much to my surprise, I liked the C code a lot better. It was simpler and cleaner. I would never program a complex application in C, but in this case I did not need the flexibility that comes with encapsulation and interfaces. I suppose the lesson I should learn is that I over-engineered the project, and I could have made the C++ code simpler, too. I like using destructors and exceptions for cleaning up resources.
Sign in to Reply
Armands117
8/27/2009 5:49 AM EDT
I have used C++ for large embedded systems as well as tiny projects (like bootloaders) and now using C++ whenever project is not constrained to usage of C only.
Because often embedded software deals with hardware representing the physical world C++ with its OO approach fits more naturally than C.
Another good thing about C++ is that you are not obligated to use all of its features; for example: I did not use RTTI and exceptions handling in bootloader projects.
Some principles for using C++ can make life a lot easier:
1) Do not make unreasonable assumptions. Understand each feature of language you are going to use and accept consequences. Check C++ standard, make trivial ad-hoc test cases and check the resulting assembly code whenever in doubt.
2) Agree within a team on a set of features of language that may be used and features that shall not be used.
3) Cast error-finding work onto compiler whenever possible. Avoid constructions that keeps compiler from detecting errors and fix all compiler reported warnings.
Sign in to Reply
Armands117
8/27/2009 8:55 AM EDT
I have used C++ for large embedded systems as well as tiny projects (like bootloaders) and now using C++ whenever project is not constrained to usage of C only.
Because often embedded software deals with hardware representing the physical world C++ with its OO approach fits more naturally than C.
Another good thing about C++ is that you are not obligated to use all of its features; for example: I did not use RTTI and exceptions handling in bootloader projects.
Some principles for using C++ can make life a lot easier:
1) Do not make unreasonable assumptions. Understand each feature of language you are going to use and accept consequences. Check C++ standard, make trivial ad-hoc test cases and check the resulting assembly code whenever in doubt.
2) Agree within a team on a set of features of language that may be used and features that shall not be used.
3) Cast error-finding work onto compiler whenever possible. Avoid constructions that keeps compiler from detecting errors and fix all compiler reported warnings.
Sign in to Reply
mark.nelson
8/27/2009 9:25 AM EDT
I love C++ more than life itself, but this statement:
>I would be interested to see
>concrete examples of how using
>constructors can cause security
>problems.
glosses over the horror of undefined initialization order of globally scoped static objects. This can indeed cause all sorts of security problems through buffer overruns and various other nastiness. Try using an std::string before the object has been initialized, no telling what might happen.
This is a super-weakness in current C++, and the solutions are awkward and fraught with potential for mistake. Embedded programmers seem to be more prone to creating global statics than other types of app developers so this is a real issue, and not one to be blithely talked around. I've seen it blow up in extraordinary ways.
The comment about static analysis tools should not be applied to this problem. Any weakness in the language that requires the use of some other tool that may or may not be available, and may or may not work with your compiler, is still a weakness.
- Mark
Sign in to Reply
ddaly
8/27/2009 10:09 AM EDT
A word I haven't yet heard in this discussion is abstraction. I once heard Stroustrup (at ESC, many years ago) say that we should work in the highest level of abstraction we can afford. To me, at the time, that statement was transformational; it knocked me out of a very entrenched, "do-it-yourself" mindset.
Many take the concept for granted, but the idea is important to me because of how it enables me to think about the systems or processes my software controls. Regardless of how many details I can keep in my head at once, the fewer I have to take into account at the moment, the simpler my job (and the software I'm writing at this instant) will be. Good abstraction involves good design, appropriate encapsulation, and putting the right code (and data) where it belongs, at the right level, making all levels clear and simple.
Well-abstracted code is easier to write, debug, and change, and less error-prone. C++ provides techniques for abstraction that are easy to master. Some abstractions are built into the language or the library, and others are ones we roll ourselves. All are useful in allowing us to concentrate on the right level at the right time. This is a particular area where C++ shines in a way C does not.
Sign in to Reply
Itzhak Ben-Akiva
8/27/2009 10:49 AM EDT
Dan, you've got another supporter. There has been, for too long, C superiority over C++ claims based on myth. I have worked in many embedded system project, which wrongly used C where C++ would have made the development must simpler and leaner. And, currently I'm redesigning an entire software program with over half-million lines of code that could have been made simpler by adopting OOD and C++.
It's a pity that many software engineers/managers fight the religious battle for a particular language instead of adopting the language that best solves the problem at hand.
Sign in to Reply
DrOctavius
8/27/2009 12:39 PM EDT
Mark,
In some cases, you can use a method like .init to put your initialization code there and call it from where/when you believe is safe and not put this code in the constructor.
C++ is a superset of C. I don't see any point where C is better than C++.
If Ive a good compiler/STL implementation in my target platform, that's enough for me to use C++.
Sign in to Reply
KenPeek
8/27/2009 1:18 PM EDT
I like many of the features of C++, like classes, inheratance, encapsulation, stronger type checking, etc.-- and these should be very useful to create better embedded systems. But there _ARE_ features of C++ that should be avoided like the plague if you are programming for a real-time embedded system.
I think that if you are going to use C++ to program a real-time embedded system, that you should restrict your use of the C++ feature set to that of the proposed "EC++" standard. This will keep you out of most kinds of trouble that you can get into with C++ and embedded systems.
Sign in to Reply
bboyle
8/27/2009 3:41 PM EDT
I have been programming in C since 1982 and C++ since 1990. Each has its place in my software development tool set. The more complex the system, the more appropriate I find C++. It has often been said that C is a high-level assembler, and I find that is true when it comes to low-level performance. But, for highly available, large-scale, distributed systems, C++ is a far superior tool. I have designed and developed significant commercial realtime systems in C, and major transaction processing systems in C++ that run about 80% of the 300mm semiconductor fabs worldwide. For cell control systems, C works well, but I would NEVER use it to develop an MES (Manufacturing Execution System) that has to run a fortune 100 manufacturing plant.
Sign in to Reply
DKC
8/27/2009 8:48 PM EDT
C++ is a superset of C, so everything you can do in C can be done the same in C++. The pitfall is that "clever" programmers will do very ingenious things in C++ that later maintainers have a hard time understanding.
It's my language of choice for large projects, but it's a double edged sword - handle with care.
Sign in to Reply
Theckyam
8/27/2009 9:05 PM EDT
{
Dan.AddAnotherFellowToYourSide().
}
As a programmer, team lead and a manager, I would reccommend high use of C++ where available. As many people rightly commented, the real problem with C++ is *the people who never executed complete real projects in C++*. I am sure if someone goes to code in C++, they'll never come back to C.
Another major problem is that the compiler support for C++ provided by Vendors is NOT as much supported and optimized as C compilers. Once these 2 hurdles are overcome, programmers should be able to gain real advantage of C++.
We need to just use a profiler to find bottlenecks and optimize them with anything you want (asm or C for that matter !?) for the critical code alone, that's enough.
Unfortunately, I never got to convince my current collegues on usage of OO and C++ -> No one seems to be interested even to try it out on a pilot project :(
Sign in to Reply
Theckyam
11/19/2010 8:17 AM EST
Thanks for taking time to reply.
Though I am a year late in replying to you, I am entirely with you on your lines of strategy for getting to convince people on a step-by-step;non-invasive/disruptive strategy. But the real point is not about selling - I would like them to see the concepts and beauty associated with the language too. And I think this can happen once they have understood the system-wide benefits of using OO. And for the past one year, I've got a few of my collegues convinced at least about using the OO concepts with C; rather than talking to them about C++ (which seems to them totally alien) - just on the lines you've been advicing me to do. Let me see if this would lead them someday to try an OO language by itself for our developmental activities to avoid spaghetti code (as Jack would call it).
Sign in to Reply
Armands117
8/28/2009 2:01 AM EDT
Theckyam,
People are skeptic in front of new revolutionary technologies (even if these are not new actually), thats ok. If you are truly interested in success of your colleagues, take a time. Treat your colleagues as customers; you have to sell to them. Start with OO. Do not present it as something new and radical. Seek for issues in current design that could be solved using OO design. Even if it is not possible to start entirely new project using OOD, start gradually with a smaller part (module, sub-system, etc.), have it successful and than present the results and benefits to colleagues. It might be the case that your colleagues are already using some of OOD principles here and there without being aware of it. Once the team has accepted OOD as a good and natural approach, present C++ as a logical fit for OO programming.
I recall my efforts convincing customer to switch from well established but manual versioning system to subversion.
Armands
Sign in to Reply
Ratgebber
8/29/2009 6:11 AM EDT
The class war doesn't worth the effort. If git is the quintessential app then quoting Linus' succinct post from a year ago helps to put the real issues of C++ back in focus: linux-foundation.org>
=============================================
From: Linus Torvalds
Subject: Re: [RFC] Convert builin-mailinfo.c to use The Better String Library.
Newsgroups: gmane.comp.version-control.git
Date: 2007-09-07 01:12:18 GMT (1 year, 51 weeks, 2 hours and 48 minutes ago)
On Fri, 7 Sep 2007, Linus Torvalds wrote:
>
> The fact is, git is better than the other SCM's. And good taste (and C) is
> one of the reasons for that.
To be very specific:
- simple and clear core datastructures, with *very* lean and aggressive
code to manage them that takes the whole approach of "simplicity over
fancy" to the extreme.
- a willingness to not abstract away the data structures and algorithms,
because those are the *whole*point* of core git.
And if you want a fancier language, C++ is absolutely the worst one to
choose. If you want real high-level, pick one that has true high-level
features like garbage collection or a good system integration, rather than
something that lacks both the sparseness and straightforwardness of C,
*and* doesn't even have the high-level bindings to important concepts.
IOW, C++ is in that inconvenient spot where it doesn't help make things
simple enough to be truly usable for prototyping or simple GUI
programming, and yet isn't the lean system programming language that C is
that actively encourags you to use simple and direct constructs.
Linus
=============================================
Sign in to Reply
salva004
8/29/2009 8:38 AM EDT
Thank for your for the article, I find it useful since I am working with C++ for the GUI and C libraries and C code for the Audio in my application.
// Sal
Sign in to Reply
antennahead
8/31/2009 11:39 AM EDT
One of the main points of the "Real Men Program in C" article was that Academia isn't doing a good job of teaching C. I think we can all agree that it's probably better to learn C first before learning C++. I think we can also agree that CS departments and EE departments have dramatically different philosophies- CS is more concerned with abstraction, and EE is more about how the machines actually work. In the real embedded world, professionals need to understand both to make an informed decision. The 10%-15% added overhead mentioned for C++ in this article can be more than enough to push a given project into a larger, and therefore more expensive, MCU than needed for C. If you have to room, great, use C++. But we often can't estimate code size very well and starting with C is a more conservation approach in this regard- you can always convert over to C++ and add the abstraction at the end. Though, in practice we wouldn't do that because our managers would have us working on the next project...
Sign in to Reply
RHinNY
8/31/2009 1:17 PM EDT
The arguments of using C versus C++ for embedded programming are reminiscent of the Assembler versus C arguments. They have similar roots: an established, well understood technology being displaced by a more modern technology that can be used more efficiently for more advanced applications. The adoption of C++ is driven, not by fashion, but by embedded applications that are significantly more complex. The migration to object oriented languages for embedded aps is probably inevitable and there's no more likely candidate right now than C++.
It's a huge leap in design methodology to object oriented from structured programming. How many times have you designed a C program by writing pseudo-code algorithms then fleshing out the pseudo code into subroutines and building up your program from there? You'll end up continually redesigning if you try to do that with objects. In OO programming, you need to figure out what your objects are (i.e. your C++ class names) and what you do with the objects (i.e. your methods). As you do this, you begin to understand the relationships between the objects which determines inheritance and member/method access.
Since C++ is a superset of C, it's very tempting to just start with a C file and try to convert it to C++. Don't do it! Always design first; then starting with your methods, go back and look for the appropriate C routines in your libraries that can form the core for your methods. Pure calculation routines can often be moved mostly intact (either as class or instance methods). If your C routines take structures with either substructures or pointers to other structures, you'll probably need to redesign them as objects.
Where can C++ (really any OO language) shine in embedded systems?
1. Encapsulation - it's not just for data hiding! It allows a class to enforce appropriate state changes on its data. In multithreaded situations, you can bury the synchronization in the class. You can create non-blocking synchronous methods that internally queue operations to asynchronous service threads and the class access methods can guarantee that external state of the object is always consistent. Even in non-multithreaded situations, your methods can always provide a valid result by enforcing data access protocols. This isn't trivial but, with the appropriate design, the code is simpler to write and the methods are easier to use than the equivalent code in C.
2. Inheritance is the key to reusable code. It needs to be used sparingly and often you're implementing interfaces not inheriting methods directly. Think of inheritance as a guarantee that an object always behaves properly for any of it's methods independent of the state of its internal data.
But, C++ isn't without it's problems especially in embedded applications. C++ like C allows you to do things that just shouldn't happen. Here are some things to keep in mind:
1. A local variable for a new object should usually be a pointer that's explicitly set with the result from a constructor. Don't implicitly instance an object for a local variable by value on the stack. For all but the most trivial classes, this is often a mistake.
2. When a class has multiple constructors, use a static method to jacket each constructor. The static method name gives you a more appropriate name and makes it explicit in the source which variant of the constructor you're using.
3. Avoid overloading the basic C++ operators. It looks cleaner when you first write the code but when you have to debug it or maintain it, you have to figure out whether any of the variables in an expression invoke methods. It makes it way too easy to embed a method invocation inadvertently in the middle of a calculation in a loop and kill your performance. If someone dumped a pile of code on you and you saw "a = b + c;", aren't you going to assume that "a", "b", and "c" are numbers? Would you even stop to think that one of them is a matrix? The obvious is easier to maintain than the cute.
4. Don't use the "Embedded C++ Subset"; gcc C++ has been ported to the most popular architectures. Among other limitations, the lack of exception support in EC++ substantially alters the design of any robust C++ program. This isn't a technical issue; the issue is training people and the additional cost of maintaining non-standard design practices. If you're going to make the transition to C++, why choose something that can significantly alter your application design?
5. Be very careful with the standard libraries; just as unrestrained use of the Standard C Library can wreak havoc with size and performance of C programs, the Standard C++ Library and Standard Template Library should be used judiciously.
It seems to me that the major issue for embedded applications with C++ and Object Oriented programming is that it takes you one step beyond C which is already one step above your processor architecture. It's not very productive to argue C versus C++. For more complicated system designs, C++ is a clear winner (assuming you can find people who understand C++ and embedded programming) but, if your application isn't any more complicated than what you've done before and you're dealing with an old hardware platform, why would you want to introduce a major variation like changing your language and design?
Use the language that's most appropriate for your application. Often that still means C but you'll probably increasingly find that an Object Oriented language is more appropriate and you'll move to C++, Objective C (like on the iPhone) or even Java. They're all good languages when used appropriately.
Sign in to Reply
Lundin
9/1/2009 5:58 AM EDT
This debate is becomming quite interesting, especially as C++ is presented as "the modern language", while it is in fact almost as old as C, both in terms of birth date (ancient 70s) and ISO standard date (1990 versus 1995). C++ is just as C, a terribly old language. And while those two remain the most speed/code efficient high-level languages, they are both having blantantly ugly syntax compared to the some successful modern languages like Java and C#. We should have that in mind that we are arguing over which dinosaur is the better, since we are lacking something suitable to replace both these ancient languages. I would think one big reason while C is still so popular is that few see the use in upgrading to Dinosaur 2.0.
I would not question the usefulness of object orientation, knowing about it is a must no matter language. If you don't design your C programs with an object-orientated mindset, they will become messy indeed. That is however not the language's fault. Object orientation is an abstract model, that a language can provide varying amounts of support for. Just because you type out "class", it doesn't make your program object oriented. A poor C++ programmer is free to use the public keyword for anything, or to leave out private/public completely. So please, stop saying that OO == C++. If you look solely at the program syntax and not the design, the OO purists will certainly call C++ an ugly hybrid abomination.
---
Some comments about the article:
"I know of no place where the C++ language performs dynamic allocation or recursion behind the scenes."
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 at link time without a heap, so I am most curious to read about that in upcomming articles.
---
Regarding the arguments against private encapsulation with static variables, they are quite outdated. First of all, the current ISO C standard 9899:1999 has full support for inlining. Though even if you write in ISO C 9899:1990, all modern compilers for that language support inlining as part of the optimization process. This is especially true for embedded compilers for microcontrollers, where you have a limited amount of registers and stack space, and wouldn't want to push everything on the stack for those reasons.
If we put compiler optimizations aside, C/C++ will not inline unless the programmer remembers to write the inline keyword. And the compiler is usually more qualified than the programmer in determining what to inline, so the usefulness of that keyword can be questioned. Inlining isn't really the programmer's concern any more.
---
Regarding failure to initialize objects, that is a hazard no matter language. I would encourage the use of static analyzers for this as well.
---
Regarding arguments regarding the unreliable RAM, they are indeed independant of the use of constructors. Because you have the same problem with initialization of plain static variables. This has been used as an argument against the usage of both C and C++ in systems with non-volatile memory, labeling them both unsuitable as they assume that things are in place before the program is started. However, you can choose not to initialize static variables but instead set them in runtime. But you cannot choose to not run constructors.
Skipping static initialization is done as "defensive programming". People without experience from safety-critical systems typically find the whole concept of defensive programming incredible alien: "Why are you writing code for situations that can theoretically never appear?". That's a topic for another discussion.
Sign in to Reply
RickyW
9/1/2009 3:16 PM EDT
C++ to C, is just like C is to Assembly.
One word : Inevitable (in embedded system).
The never ending critisms of C++ simply stems from:
1.C++ over-flexibility, which makes the less experience shoot himself in the foot.
2.Lack of good standard library for embedded systems. As STL simply sucks.
In C++
1. The full power of C is still available.
2. Since much of modern C programs are designed to model object-oriented concept, why use a non-object-oriented language in the first place?
An example is Linux Gobject/GTK.Whereas in KDE, which is based on C++ Qt library, its much quicker to develop applications.
The large number of KDE apps is evidence of this. Even in Windows, how many people still use raw C?
3. A program in C++ is around half that of C in text code, which cut cost in development, testing and maintanence.
While the C++ compiled code size may bloat alittle if not designed correctly, it is cheaper to have it that way than to have larger text code base.
4. Moreover, the well-designed C++ library could be used in both PC and embedded systems
In PC world, C has been replaced almost entirely in Windows.
It will be similiar in embedded system, minus at most the OS and device drivers components.
Furthermore, C++ compiler and tools are more readily available in embedded space, compared to other higher level languages.
While C++ is not perfect, it is inevitable for embedded use, until a better replacement comes.
The only difficult part is to find good and experienced engineers in C++ in the embedded domain.
Personally, with 10 years of embedded system programming, it is now a pain for me to look at C programs, which look so backward in design methodology.
Sign in to Reply
S.T.
9/1/2009 4:15 PM EDT
Maybe you have to read the original thread to understand Linus position. Reading only others comments about this story may give you a false picture. I wont explain you here the whole story. Please read it by yourself and judge:
http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918
This is, on a much smaller scale the CC of the Torvalds-Tanenbaum controversy which made flowing a lot of ink at the beginnings of linux. I feel the same kind of motivation is at the origin of the paper we are commenting now.
If you are curious and interested in contemporaneous history this read the The linux-kernel mailing list FAQ :
http://www.tux.org/lkml/#ss15
Sign in to Reply
DrOctavius
9/1/2009 11:05 PM EDT
Lundin,
"And the compiler is usually more qualified than the programmer in determining what to inline, so the usefulness of that keyword can be questioned"
Out of topic, but I'm wondering....If I have a function with a small body and I don't have the inline keyword, how the compiler will now if I want to optimize my code for speed or space?
"Inlining isn't really the programmer's concern any more."
Compilers are getting better and better for sure, but this has nothing to do with in-lining, why? because the compiler cant guess what the programmer need.
Sign in to Reply
Lundin
9/3/2009 4:45 AM EDT
There exist no compilers that come without compiler settings. Many compilers have options "optimize for speed", "optimize for size". Good compilers even visualize how your current compiler settings will affect speed, size, debugging complexity etc.
Also if you have a very small function the compiler should perhaps inline it no matter, depending on CPU architecture. Because there will be overhead instructions of pushing things on the stack/registers, calling the function, returning from it and so on. The number of instructions for calling the function may take up more space than the actual code inside the function. Whether such functions should be inlined or not won't be obvious to the programmer unless they disassemble the program.
It is also possible for the compiler to make assumptions of inlining depending on how many times a function is called. If it is called from within a loop for example, it may be wise to inline it even if you desire a small program.
Sign in to Reply
woodchan
9/3/2009 10:04 AM EDT
I wonder most of the proponents of C++ here are actually using a "better C", or objective C, rather than (a full-fledged) C++.
Recently I converted the SoundStretch from C++ to C. The exe file of C++ occupies more than 200K, while below 20K for C. Yes, I removed EHS, abstract class and all virtual functions, but the discrepancy worth a frown.
Sign in to Reply
AlPothoof
9/3/2009 11:30 AM EDT
Lundin,
Dan Saks wrote: "I know of no place where the C++ language performs dynamic allocation or recursion behind the scenes."
To which you replied: "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. "
EXACTLY! If you do string manipulation, it will do dynamic allocation. Is this inherent in the language? No, if I'm being honest, it isn't. But, like you, I can't imagine the string class being implemented without it.
Likewise I am highly suspicious that any library module that does list manipulation will do it through recursion; it isn't required by the language but, based on my reading, it does appear to be the preferred method of C++ programmers. And my experience is that recursion is a highly-risky endeaver that has no place in embedded systems.
(By the way, I am the author of the original comment to which Dan is responding here. I actually LIKE C++; I think you can do a lot of really neat stuff with it, stuff that seems natural to my mathematical mind. I also think the core concepts of OO-ness [encapsulation, data hiding and polymorphism] can result in a system which is unmaintainable because it is difficult to understand. A competent C++ programmer MUST be more disciplined than a C programmer and my experience is that it is a rare programmer who is disciplined and versed in best practices. And embedded programmers seem to be worse in this regard as most of them didn't start in software [except CS majors and they seem to have a whole other set of bad practices].)
However, I am going to join with DrOctavius in questioning your statement "And the compiler is usually more qualified than the programmer in determining what to inline, so the usefulness of that keyword can be questioned."
Since the inline keyword is only a suggestion to the compiler, I may agree with you in this specific instance but I'm always a little leary of the decisions the compiler makes about things like this. Yes, there are settings which let me customize how the compiler handles these things but the granularity isn't always what I'd like.
Short story: longer ago than I'd like to admit, when FORTRAN was the preferred "high-level language" for real-time and process control, a systems analyst for a computer company was extoling the virtues of their new optimizing compiler: "It can generate assembly-level code as good as you can." ("Good" is the proper term here, as we were discussing the quality of the code, not the ease with which it could be generated), To this I replied, "no, it can generate code as good as YOU can." After a moment's reflection, she agreed with me.
Here is what (I hope) she realized from my response: the quality of the assembly-level code was as good as the team producing the compiler could make it which, pretty much by definition, would be average. It would be as good as I could produce only if I produced average code. If produced poor code, the compiler code would be better; if I produced excellent code, mine would be better. (As an aside, I was at least as likely to work in assembly language as I was in FORTRAN at that time and I did a lot of systems-level and driver work; both she and I knew that I was a lot better than average.)
I would probably agree with you that, for the average software engineer, letting the compiler make these kind of decisions is a good choice. (And my experience with young software engineers in the past few years has been that, though VERY knowledgeable about C++, OOD, UML, modeling, etc., they seem to lack an underlying UNDERSTANDING of what's going on with what they're using.) Some of us, though, still do debugging at the assembly level and actually look at assembly language listings; we really want, and need, to know what's going on in the compiler and in the microcontroller. And, I'll be honest, there are times I look at those listings and shudder a bit at what the compiler did: it may be a good general solution but is hardly optimized for either speed or size. (This, by the way, is not a new feeling; I felt it with those old FORTRAN compilers, too. And even high-level code produced by code generaters [including some I've written] horrifies me.)
Of course, the only solution to that conundrum is to write everything in assembly but that takes too long and there are too few decent assembly language engineers available.
Sign in to Reply
sonicpp
9/3/2009 8:49 PM EDT
Hey Dan... Neil (from Vegas) here...
I figured "C = Real->Men();" would stir up some dust.
The argument is not worth fighting. I have found that C and C++ both have their place in embedded programming. They are tools at our disposal. It would be like saying I dont need any regular screwdrivers because I have an 18.5 Volt Black and Decker Firestorm with Phillips and straight screwdriver attachments.
Sometimes you just need a screwdriver!
Sign in to Reply
Lundin
9/4/2009 5:35 AM EDT
Well... this is drifting off-topic. Whether the inline keyword or an optimizing compiler is the best isn't really relevant to the discussion. My point here was that inefficiency of non-inlining isn't much of an argument against the way C does private encapsulation. And as I previously pointed out, standard C (ISO 9899:1999) has full support for inlining.
Sign in to Reply
Dan_Saks
9/4/2009 6:51 PM EDT
Yes, C99 does indeed have inlining, but you can't use it to implement "encapsulation by separate compilation" without compromising the encapsulation. That is, you can't use inlining unless you declare the "encapsulated" data with external linkage in the same header as the inline function definitions, which in turn, eliminates compile- or link-time enforcement of the encapsulation.
This is very similar (though not identical) to the problem I described in "Incomplete types as abstractions" at http://www.embedded.com/columns/programmingpointers/16100434. (It's under the subheading "A possible loss of performance".) As that article points out, it doesn't matter whether you use inlining as in C++ or in C99 (they are a bit different), or even whether you implement inlining using function-like macros in C89.
Sign in to Reply
lwriemen
9/8/2009 8:47 AM EDT
I could recast your article as, "Poor reasons for rejecting [insert some other 3GL]", but I can't help but wonder when we are going to move to a higher level of abstraction. I have seen C++ (and the occasional Java) project get mired in many of the same issues as C projects. A lot of the problems lie in the distractions presented due to the abstraction level focus of the language. i.e., developers spend as much time with the implementation problem space as they do the application problem space.
Therefore, I think it's time to move the ball forward and say, "Serious software developers program in Executable and Translatable UML (xtUML)." http://en.wikipedia.org/wiki/XtUML
Sign in to Reply
Bibliognost
10/2/2009 8:52 AM EDT
On Dan's comment
>
> I know of no place where the C++ language performs dynamic
> allocation or recursion behind the scenes.
>
I taught an introductory C++ class, targetted at incoming
students, at a local community college this spring. What
alarmed me about the text, and the way it is taught, is that
dynamic memory allocation is the DEFAULT way to design an
algorithm. It is embedded in all programming examples,
while the concept of static memory allocation is barely
mentioned and never illustrated. Remember that for most of
those in my class, this was the first programming language
they had ever seen.
Go through a recent college textbook if you don't believe
me.
After 20 years using it, I still find C syntax challenging,
and infrequently have to check the assembly language to
discover what amounts to my typo, because "I didn't know C
would do that!"
I fear that as old timers like me get put out to pasture,
the next generation will have to learn how dangerous dynamic
allocation can be in an embedded project in the school of
hard knocks.
Sign in to Reply
aray
10/12/2009 2:16 PM EDT
My 10 cents on the subject: if one looks at the volumes with introduction to the three programming languages it is not hard to notice difference in thickness: C - half inch (1.2mm), C++ - 2 inches (5 mm), Java - 1 inch (2.5mm). It is very much proportional to how long it takes to master the languages. If one starts programming with all three languages at equal proportion C mastery will be achieved before any other. And by the time C++ ace achieves his(in rear case "her") prime time, an equally gifted C guy have produced a lot of good code.
I prefer C for any embedded project hands down. And if there is a need for GUI then Java beats C++ by far.(I never used compiled Java, probably there is a chance that it will beat C++ even on embedded side)
Sign in to Reply
dtatsan
10/21/2009 3:08 PM EDT
Dan,
I like DR Octavius have also been developing embedded systems for over 20 years starting in assembler, migrating to C, and then C++ and of the three I work in C++ whenever possible. I work on projects that require the support of multiple instances of the same device. Using C++ I have been able to write code faster because once I have it working for one device extrapolating it to 2 or more requires little extra work. Using C++ I have actually written code that runs faster than it's C counter part by removing repeated tests for which instance of the hardware is currently active. The code is easier to read and update.
Sign in to Reply
returningTarzan
10/22/2009 6:26 AM EDT
It's very simple, really.
C++ is a superset of C. Anything you can do in C, you can do in C++. The performance overhead of C++ does not exist, until you start using specific C++ features like virtual member functions, but if you use them in place of the equivalent C construct (function pointers) again you have absolutely zero overhead. I've heard all kinds of nonsense about C++. The idea that it produces memory fragmentation comes from a misunderstanding regarding the "new" operator, an assumption that because it's provided by the language, not only must it be used, but it must be used in its default implementation which is essentially a wrapper for malloc(). The truth is that C++ does not force any memory allocation schemes on you. You can allocate objects on the stack, in global arrays, inside structures, inside other objects, etc. The idea that it introduces vulnerabilities because of the order in which static globals are constructed is equally silly; this will only ever be a problem when the programmer does not know the language he is working in and makes false assumptions. The solution is simply to avoid globals altogether; globals are awful design anyway, even in plain C.
In my experience the underlying issue is that embedded developers tend to be bad programmers. Go ahead and rip my head off, but I've seen enough embedded code to say that with a clear conscience. There is simply no good argument for stubbornly clinging to C, except not having the experience to work with C++ (or being forced to by a manager who doesn't know better, or supporting legacy code that wouldn't mesh with new OO code, etc., but you get my point).
An embedded system is not easily conceptualised in procedural terms, but it is perfectly modeled in object-oriented terms.
Sign in to Reply
lwriemen
2/28/2011 7:37 AM EST
I was sucked in by the tag line in my EET email for this posting, "Choosing a programming language should be a well-informed choice."
The real problem is that debating C vs. C++ doesn't imply well-informed participation, as there are much better choices available. One commenter compared going from C to C++ like going from assembly to C. This isn't a valid comparison. C++ doesn't supply as big of an abstraction step; it is more like a half-step in abstraction. In order to get a full step in abstraction, you need to go to Executable UML (Mellor and Balcer) or something similar.
If you are programming in Executable UML, you can compile your models into C and avoid any overhead that C++ brings, while gaining all of the OO benefits.
Sign in to Reply
GordonScott
2/28/2011 11:18 AM EST
Me too.
You'd think EETimes would resist trolling.
Next week's issue should be on "the best editor"
:-)
There is a whole bunch of dichotomies with C and C++.
Do I want it for a large or a small project?
User-level or embedded and/or realtime (OK, that's a trichotomy).
How critical is determinism?
Why is C++ "a better C" if C++ is essentially the same as C.
Abstract or not abstract?
And In the design or in the code?
Now I'm a whole-hearted supporter of OO principals, abstraction, modularisation, scoping, defensive programming and all the other stuff that helps make code `friendly', so it disturbs me when I spend hours just tring to find where the entry point is of a program, or when the code starts calling function after function and the debugger can't tell me why, where, or whether the code is supposed to be going where it is. How am I supposed quickly and intuitively to spot that some high-level code had an overloaded something-or-other?
Abstraction can be nice for design, but _can_ also be a nightmare for debug and maintenance.
I'd be interested in objective figures for maintenance costs for C versus C++ (or indeed the other `better' C derivatives).
Last time I looked, a few years ago in fairness, the `easy to use and maintain' C++ was costing three times as much to maintain as was C.
Hopefully that's improved!
Sign in to Reply