Barr Code
Real men program in C
Michael Barr
8/1/2009 12:00 AM EDT
A couple of months ago, I ate a pleasant lunch with a couple of young entrepreneurs in Baltimore. The two are recent computer science graduates from Johns Hopkins University with a fast-growing consulting business. Their firm specializes in writing software for web-centric databases in a language called Ruby on Rails (a.k.a., "Ruby"). As we discussed many of the similarities and a few of the differences in our respective businesses over lunch, one of the young men made a comment I won't soon forget, "Real men program in C."1
Clever though he is, the young man admitted he wasn't making that quote up on the spot. That "real men program in C" is part of a lingo he and his fellow computer science students developed while categorizing the usefulness of the various programming languages available to them. Exploring a bit, I learned the quiche-like phrase assigns both a high difficulty factor to the C language and a certain age group to C programmers. Put simply, C was too hard for programmers of their generation to bother mastering.
Is C a dead language?
For today's computer science students, learning C is like taking an elective class in Latin. But C is anything but history and not at all a dead language. And C remains the dominant language in the fast growing field of embedded software development. Figure 1 summarizes 13 years of relevant annual survey data collected by the publishers of Embedded Systems Design.

The discontinuity after 2004 is necessary because the phrasing of the question and permissible answers were changed in 2005. Prior to 2005, the question was phrased, "For your embedded development, which of the following programming languages have you used in the last 12 months?" In 2005, the phrasing became, "My current embedded project is programmed mostly in ____?" Prior to 2005, multiple selections were permitted. This meant that the aggregate data was allowed to sum to over 100% (the average sum was 209%, implying many respondents made two or more selections).
The biggest impact of the survey change from multiple selections to one selection was on the numbers reported for assembly language. Prior to 2005, assembly language was present in an average of 62% of all responses to this question. This should not be surprising, as it is well known that most firmware projects require at least small quantities of assembly code.
After 2004, assembly becomes a minor player--averaging just 7% of all responses across five survey years.2 This data more closely represents the percentage of projects written mostly or entirely in assembly. The data also show a decline in the popularity of that programming style, from 8% in 2005 to 5% in 2009.



Caprica
8/2/2009 6:51 AM EDT
Im a second year comp-sci student at the University of Waikato (New Zealand), and I personally love programming in C. Currently looking at linux kernel source code with a hope of being able to make some useful contributions. I have done some assembly in a paper last semester (final assignment was to implement a preemptive multi-tasking kernel in assembly (for a computer designed at the Uni)). Im also planing on buying an embeded computer at some point with the intention of writing some (semi) useful software on in both C and whatever assembly language it takes. Im not sure how to get other students intersted in lower level programming. I guess I just like a challenge and hate Java's verbosity and its over-protectivness it prevents truly learning what the language is doing.
Sign in to Reply
twomeyw2
8/2/2009 11:19 PM EDT
I remember having to program some Intel chips in C while I was in school getting getting my EE degree. We pointed out to the prof that our sole software class (intro to software) used Java. He kind of laughed and said "teach yourselves c, you're EE majors!" It always seemed like there was a rift between the EE profs and the software profs. Some of the EE profs had an elitist complex and refused to even acknowledge software was an "engineering" discipline, it was something beneath them. I don't know if it is like this in other schools but I think this is part of the problem that leads to self taught EEs with varying unconventional styles coming out of school. So, the solution... have the software profs and EE profs sit down for a beer with Obama and some real world embedded coders, maybe you can leave Obama out.
Sign in to Reply
Alex OD.
8/3/2009 1:36 AM EDT
Now I think about it, there was no real EE component to my BSc in CS (with maths). I did have one half unit if Logic Design, but it didn't count to the degree, it was just a extra we did for fun. All I knew about electronics came from high school physics classes.
I did real embedded work for several years before encountering an ADC or DAC, so to me, the rest of the board was just "turn it on, turn it off". It seems all the embedded folks I met were EE majors, or apprenticed electronics guys, I was the oddball.
Offering embedded degrees would not help, as no one would know to take them. Most of us know programming goes with computers. Some know electronics is made up of resistors, capacitors and diodes. But before we get to university we don't know embedded even exists, so how would we know to study it?
At least I know now I am a real man.
Sign in to Reply
robert.berger
8/3/2009 7:44 AM EDT
Hi,
10 years ago real men and women programmed in Assembly now they program in C. I'm, among other things, TA for an embedded systems introductory course in cooperation with CMU. For students who attend this course prior knowledge of Java is considered harmful!
Just for the fun of it you might as well want to have a look at what Linus Torvalds thinks about C and C++: http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918
Regards,
Robert
--
Robert Berger
Embedded Software Specialist
Reliable Embedded Systems
Consulting Training Engineering
Tel.: (+30) 697 593 3428
Fax.:(+30) 210 684 7881
URL: http://www.reliableembeddedsystems.com
Sign in to Reply
DaveArmour
8/3/2009 1:27 PM EDT
Being unemployed and looking for a job I am amused at all the "embedded" jobs that require Java, C# and scripting languages. Are they really doing embedded work? To me embedded work requires knowledge of the hardware and how the software interacts with it and assembly and C are the only two languages I have found that do that in a fairly deterministic way. Unless I am missing something, all the rest are just kidding themselves.
Sign in to Reply
cfbsoftware
8/4/2009 1:02 AM EDT
Maybe that should be "Real old men program in C" ;-)
Anybody suffering from the delusion that C is the only viable 'high-level' language for embedded development should have a good hard look at Oberon-07.
http://www.inf.ethz.ch/personal/wirth/Articles/Oberon.html
It is as powerful, if not more so, than C but is much less prone to human error.
Chris Burrows
Development Manager
CFB Software
Armaide v2.1: ARM Oberon-07 Development System
http://www.cfbsoftware.com/armaide.htm
Sign in to Reply
GordonScott
3/20/2012 11:23 AM EDT
I accept that a good hard look may be worthwhile.
But when I looked, I followed the link "Oberon at a Glance" and read the very first line:
"No access to variables that are neither global nor strictly local"
Which combination of syntactical clumsiness, double negative and no full stop made me immediately walk away.
Sign in to Reply
NevadaDave
8/4/2009 11:13 AM EDT
I used assembler for pretty much all my Motorola (Freescale, for you young folks), Microchip and Atmel microcontroller projects. Once C compilers with decent IDE's became available, I never used assembler again, and quite honestly, I'm not sure I could at this point! I also use to use BASIC for PC programming, and I;ve forgotten most of that, too. For "real" embedded design (by "real", I mean designs where it's not a PC in a box, but the hardware is more-or-less invisible to the user)C seems to be a very good blend of high-level abstraction with the low-level bit manipulation.
However, I think that the reason C has hung on so long is exemplified (in a sort of backwards fashion) in the post by cfbsoftware: Oberon-07 might be the greatest thing since sliced bread, but if it's not available for the hardware I use, it's a non-player. C is available for pretty much everything nowadays, and those who program for systems that need to be able to manipulate the internal registers & peripherals that modern microcontrollers have will continue to use it for a long time.
Just as a side note: the link for the armaide 2.1 should be:
http://www.cfbsoftware.com/armaide/armaide.aspx
Sign in to Reply
AlPothoof
8/4/2009 4:24 PM EDT
Figure 1 of this article makes it look like C++ is a minor player in the embedded arena. Has anyone (besides DaveArmour and me) been watching the help wanted ads lately? At least 90% of them are looking for C++ (with some JAVA and C#). And they generally mean 2+ years of professional experience. For RTOS, they generally want Wince (sometimes embedded XP or Vista ???) or embedded Linux.
I think what I see happening is that CS programs are turning out lots of people who know these technologies and the companies figure they can leverage that knowledge by using big, fast chips. They don't care (or maybe don't understand) that none of these technologies are appropriate for high-reliability embedded and/or real-time systems. A classic case of "if the only tool you can find is a hammer, then every problem is a nail."
And, since companies are hiring people with C++ and Windows, that's what the schools are turning out. In this case, if all the problems are nails, all you need to provide are hammers.
Truthfully, I'm starting to feel a little obsolete: 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 its doing behind the scenes (and most people don't; they wouldn't look at the assembly-level output if their project depended on it). And, as Torvald pointed out, if you restrict all the risky behavior, you might better use C and be done with it.
By the way, I still keep my hand in at the assembly-language level. Most of the projects I work with use that for initialization code, if nothing else (although I see some compilers providing that code in C now) and I always do my debugging in mixed-mode so I can tell if the compiler does something unexpected (traditionally, that's been a lack of understanding on my part but I've seen more actual compiler bugs in the past decade than I had in the two decades prior, although that's still only 4 or 5). The only other language I've ever used for real-time systems was Fortran and I haven't used that in about a decade.
Sign in to Reply
cfbsoftware
8/4/2009 8:53 PM EDT
NevadaDave is obviously correct when he says that "if it's not available for the hardware I use, it's a non-player". It is early days yet for Oberon-07 - as far as I know Armaide was the first commercial implementation. However, other activities are already well under way e.g. apart from several different ARM implementations in use, I know of a Russian group working on an implementation for AVR.
I'm not so sure about the emphasis of the comment "those who program for systems that need to be able to manipulate the internal registers & peripherals that modern microcontrollers have will continue to use it for a long time", "it" being C. Microcontroller implementations of Oberon-07 also have equivalent capabilities. Typically they are non-portable microcontroller-specific capabilities so are normally provided in the form of a "SYSTEM" pseudo-module to make it easy to distinguish between portable / non-portable sections of code.
P.S. Thanks for correcting my URL, NevadaDave - how embarrassing :-(
Chris Burrows
CFB Software
http://www.cfbsoftware.com/armaide
(without the .htm!)
Sign in to Reply
raykeefe
8/6/2009 1:18 AM EDT
Thanks Michael, A very interesting article.
We develop embedded systems almost exclusively in C. This is particularly true for 8 bit processors like the Atmel AVR and also 16 bit processors like the MSP430.
We also work with a range 32bit processors such as various ARM derivatives and these are generally also done in C.
Our specialty is design for low cost electronics manufacture where we do both the hardware and embedded software side and we can significantly reduce cost or improve performance by selecting to do certain functions in hardware or software. In general, moving functions into software saves manufacturing cost but only so long as it doesn't require excessive CPU grunt to handle.
An exception to coding everything in C is some Java Embedded work with the Micro Kernel achitecture such as you find with mobile IP devices like the Cinterion modules, http://www.cinterion.com , where they are set up to execute Java applications direct from FLASH.
As to how I got into embedded C, I began my engineering life as an analogue hardware engineer and got my start in embedded C because I joined a company that needed a C programmer. The deal was, learn C between now and when you start and the job is yours. So I bought a couple of books and learnt C in 5 weeks. Of course there was a lot of subtleties I didn't understand but I was able to start cutting code on day one.
So I am grateful that that was forced upon me because I have been coding in C now for 21 years and it is a very useful skill to have.
It is interesting that it continues to grow in the market place.
Thanks again for the information.
Ray Keefe
http://www.successful.com.au
Sign in to Reply
Ray Keefe
8/6/2009 1:39 AM EDT
Can see where DaveArmour is coming from because when I think about embedded I usually am thinking small systems tightly coupled to the hardware. Because that is what we mostly do.
However Windows Embedded is another thrust where full on PCs are deployed as Internet Appliances. For these devices C# and other higher level languages make a lot of sense.
And then there are all the Linux and RTOS based systems. The world is changing.
Where I work, we develop embedded systems almost exclusively in C. This covers 8 bit processors like the Atmel AVR and up through 16 bit processors like the MSP430.
The various ARM derivatives are 32bit processors also coded in C though I can see some merit in C++ for these.
Our primary focus is design for low cost electronics manufacture and we execute both the embedded software side and the electronics hardware side. Done this way we can deliver substantial cost savings or improve performance by the choice of what is done in hardware and what is done in software. And of course, how it is done.
The one exception at the moment to coding everything in C is with the Cinterion modules, http://www.cinterion.com , using Java Embedded with the Micro Kernel achitecture. These are mobile IP devices where the kernel is probably in C but the application is executed as Java out of FLASH.
In general, executing functions in software saves on electronics manufacturing cost provided it doesn't end up too processor intensive.
I got started in embedded C due to circumstances. I was an analogue hardware engineer and I took a job with a company that needed a C programmer. They made it pretty simple. Either I was able to code in C when I started or the job went to someone else. 2 books and 5 weeks later I was able to do that. There was a lot I didn't know but I was able to start.
Although this was forced upon me I am very appreciative because 21 years later I am a very proficient and productive embedded software developer.
Thanks again for showing the survey data. It seems I'll be employable for the forseeable future.
Ray Keefe
http://www.successful.com.au
Sign in to Reply
Sundar Srinivasan
8/6/2009 3:00 AM EDT
Great article. C is certainly the language for embedded systems programming. Oberon is great, but still at its beginning stage. The statistics of percentage of embedded developers in C is encouraging, but we have to see how much of those development is really a "new development". Since most of the RTOS and drivers are written in C, modifying it would also contribute to that data. While C is certainly the king of embedded programming languages, we need to look at whether it would be in the future too.
http://sunnyeves.blogspot.com/
Sign in to Reply
ishkabbible
8/6/2009 3:37 AM EDT
Don't be too quick to dismiss very high level languages for embedded work. I design instruments for NASA, and our group codes the firmware in a mixture of C and assembly. But when I'm designing a board, I have to write code in visual basic to glue my various EDA tools together, I build very complex models in several different environments, we distribute the test data through java applets on the team web page, and we analyze the data in either IDL or Igor. Embedded isn't just about the microcontroller. When hiring a software guy, I score about 30% on their C skills, 40% on being able to pick and use the best language to solve today's crisis, and the rest divided between their bit-flipping and communication skills.
Sign in to Reply
ccorbj
8/6/2009 12:00 PM EDT
From a somewhat specialized perspective (EDA), it is difficult to see C/C++ replaced soon for heavy-lifting applications. There is unquestionably high popularity for languages a level above C (I myself am a Perl fan and would hate to be forced into C unless absolutely necessary). But I observe there is considerable fragmentation above the C/C++ level - Perl, Ruby, Python, Java, ... Java is perhaps the most established of these meta-languages, and already making inroads in handset applications, and I could forsee a day when JREs are successfully implemented directly in hardware (attempt have already been made, but I am unaware of any being wild successes)
While each of these meta-languages has value, I think a dominant standard has to emerge, with equivalent performance across a broad range of applications for C/C++ to be superceded
Sign in to Reply
K1200LT Rider
8/6/2009 12:06 PM EDT
ishkabbible,
Do you work in Florida's Space Coast area? Just curious since that's where I am.
- Brad
Sign in to Reply
ishkabbible
8/6/2009 2:31 PM EDT
Brad,
Nope - I just go there to integrate instruments and watch them launch. NASA (wisely, IMHO) chose a bunch of Arizona desert rats to go to Mars and find the water.
Sign in to Reply
udaywali
8/7/2009 4:00 PM EDT
Much like the Moore's law, the number of computing units sold per year grows about an order of magnitude in 5 years time. And interestingly, the size of the system reduces by some constant (linear), I guess. Applications that go with all these small compute-engines are not large database applications but small well defined and targeted applications. These applications may not need support of OS like uCLinux or Win-CE but a simple development tool like that from Keil. Implication of this observation is that C will continue to be one of the popular choices in the immediate future.
Chrome is an interesting case, expecting the desktop to move to cloud, giving further boost to small compute-engine market. This will require new language strategies. I am not sure of Py core but if it is small like C (or Java), you have a possible winner candidate. Give me ten years for that.
Uday Wali
Like Ray, I have been writing C since 1985.
Sign in to Reply
RussMorash
8/10/2009 1:03 PM EDT
I can also see where DaveArmour is coming from but the days of an embedded application being programmed,shipped and never heard from again are coming to an end. Be it changing settings or calibrating what equals nicely browned on that toaster more and more embedded applications need to have some communication with the outside world. For me that means also having to know and use higher level languages like C# a Java (among others) to easily (as compared to a pc app in C) develop a GUI to interact with the device.
Sign in to Reply
Susan McCord
8/10/2009 4:09 PM EDT
I think part of the reason a younger generation of software engineers is not attracted to embedded software (and hence C) is the lack of money/prestige. I have been stunned to see some job postings lately that require years of embedded software expertise/medical device control expertise/etc. and the pay rate is $30/hr! If a software engineer coming out of school can go to Google et. al. and get a hefty salary, a very cool reputation and stock options, why are they going to go into a more meticulously demanding job that requires embedded design skills? Companies that need embedded software engineers need to value them appropriately and make these jobs more attractive.
Sign in to Reply
NevadaDave
8/10/2009 4:31 PM EDT
It appears my earlier comment got lost, so if this is just reiteration, please forgive me!
My comment was that we might want to consider adding a new termo the embedded universe, something like, "Complex Embedded" to describe systems or applications that require (or uses) processors or other sufficiently complex logic that require or are best programmed by higher-level, perhaps OO languages. For example - my Atmel 8-bit designs are all done in C, not because it's the only language available for the Atmel AVR's (assembler & Forth are others of which I'm aware)but because it's readily available, has a high-enough level of abstraction to make many functions easy to write, but enough hardware manipulation to handle the basic peripherals of the device. When I wrote a Windows GUI-based configuration application for one of our electronic advance ignition systems, I used C#, because it was a good fit for that kind of system. I think that we have reached the point where we need to start differentiating the complexity/memory/cpu aspects of embedded systems before asking the question about what language we use in writing the software. New terms, anyone?
Sign in to Reply
perth1415
8/10/2009 5:13 PM EDT
Interesting article!
I've some points to make -
1. How did you arrive at the Figure-3? Could you provide the sources?
2. "Unfortunately, on-the-job learning is also poorly organized in embedded software."
- I strongly believe this point. When I joined the embedded domain as a fresher, I was throwed in to this domain, asked to write some drivers in VxWorks; then I moved into other RTOS's & finally into Firmware without any OS, mainly 802.11 MAC firmware. I never got a chance to work on Linux. I know I could have (& should have) learned a lot about the Linux kernel if I had the zeal. But somewhere I missed it. Recently during a job interview I got a feedback that meant something like this - "9 yrs of experience & you don't know Linux kernel?? Man .. you're a piece of you-know-what!". So, I've lately installed Linux on my PC & started writing a driver from scratch.
I wish somebody advised me to have a peek inside Linux kernel, back when I started in this field.
3. "Although they are smart and talented computer scientists, my younger friends don't know how to competently program in C. And they don't care to learn."
- I don't quite agree with this. As time has progressed, customers are demanding higher throughput, better stability. Based on the hardware design, you (as a software developer) are expected to deliver a certain amount of performance in your driver/firmware. If you can't do that, you lose your job to someone who can. This barely leaves any scope for "not caring to learn" your language - C.
Also, going by your statement, code written some 10 years back were better than code written in new products running in the market now? No offense meant but I don't quite agree to that.
Sign in to Reply
LukeTeyssier
8/11/2009 8:29 AM EDT
Michael Barr raises a good point. Teaching Java/Python/Ruby/TCL,etc. does not teach computer engineering. They may be useful for many tasks, but they let the student avoid really understanding what the computer is doing. They teach how to get something working quickly by trading off speed and size. In this day an age when nearly every technical professional can program (Astronomers/Astrophysicists, Structural Engineers, Civil Engineers, Mathematicians, Chemists, Biologists, Cryptographers, etc.) computer professionals need to do better than hack out code in "some high level language" to earn their daily bread. As a profession all about the tool (computer) they need to be experts in the tool and able to write the foundation that makes efficient use possible for others. They also need to be able to go as deep as necessary when things go badly with all those nice abstractions. So, if you aren't a deep expert in computers then how are you in any way more than just an assistant to those professionals who have a deep knowledge of their own expert field, plus can do your job too? IMHO, if you can't explain in detail what happens from 'printf("Hello, world\n")", all the way down to "fetch, decode, execute", then you either need to find it out, or accept the fact that your job may vaporize as soon as someone figures out how to encapsulate your limited knowledge into a GUI builder or wizard. Remember all those folks with degrees in English and Art getting $150K a year in 1998 doing html coding? Remember how they talked about the "old" economy and how they were part of the "new wave of computer scientists"? Remember how they got canned in 2001 as soon as decent web design software came out and the economy took a dip? Get ready to update your resume.
I phone screened 110 "Senior Embedded Software Engineers" to get 5-6 who could competently answer "A 'C' Test: The 0x10 Best Questions for Would-be Embedded Programmers". Note that it shouldn't be possible to graduate from a reputable CS curriculum without being able to answer these questions.
Sign in to Reply
D_Lundin
8/11/2009 11:09 AM EDT
People don't use C because it's a good language, people use C because it is the least evil option. For embedded realtime systems you really only have the choises listed: C, C++ or assembler.
Assembler will of course be used at some extent "inline", but to write whole programs in it is not an option if you want portable code. At the escalating pace in which the silicon industry plops out new processors, one can almost be certain that the program will live longer than the processor. Portable code is a must in the embedded world, therefore we need high-level languages. Private encapsulation is another good reason why.
I can come up with a few advantages of C++ over C in embedded systems, namely stronger type enforcement, exception handling, standardized inline asm, standardized inlining (C does not have this because nobody but the ISO C committee programs in C99).
But the disadvantages weight heavier in my opinion:
- Horrible, unnecessarily complex syntax. C++ is perhaps the least readable programming language of them all. Compare the syntax to Java or C# and you will grimace at the C++ syntax.
- Potential for very inefficient programs through inheritage, templates, STL etc. STL classes will enforce a heap when we don't need/want one.
- Utterly few fully compliant C++ compilers for embedded systems exist. Many claim they follow the standard, but they almost certainly forgot to implement one detail or another (who can blame them, there are so many unnecessary features). But because of this, C++ programs are very hard to port. Wasn't portability why we wanted a high-level language in the first place?
Object orientation is no good argument. 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. Initialization through constructors is not something you desire, in fact you will want to avoid this for security reasons and for reduced bootup time.
Also, the most moronic ingredients of C, like for example macros and the way integers are implemented, are not fixed in C++. So stick with C til something better comes up. Maybe some day there will be a deterministic language with fixed integer sizes.
Sign in to Reply
Jayakumar
8/12/2009 1:56 AM EDT
Bit funny but it is true. Often I love to program in C when I start a new algorithm development project. Few days might go on how to create data flow and kind of things and start coding in Scilab instead of C. When I code in Scilab, I love to keep C like code flow such that my fellow friends does not have problem when they take my Scilab script and move on to C. Some one ask why do I do this kind of long way journey?. Yes often world is not the one we like to have. For example, C is good language and gives option to write efficient code that can run on multiple hardware platforms. But look at headache it provides to fellow developer. To start with it does puts brake on fast thinking brain when they want move along algorithm development with more concentration on data flow rather then issues to keep track of things in C language. Another one which is very painful headache for Algorithm developers is that till today there does not exist good development environment IDE in which Data flow debugging can be done with ease by using graphs and other associated mechanisms . In Scilab, we dont have the above two headaches ( not fully zero but tending to zero) and makes algorithm development person very efficient in terms of time and obtained result. Thus, in my view we need brand New Tool that can provide Scilab like easy and C like efficiency. Shall we fund a new company to create such a tool?. May be we need to name that as AlgoC.
Sign in to Reply
WJT
8/13/2009 6:49 PM EDT
Real men only program in two languages and they both begin with A, Assembler and Ada. Why don't you see more non-military systems developed in those languages? Cause there aren't enough real men out there to go around.
Sign in to Reply
ESD editorial staff: SRambo
8/18/2009 12:54 PM EDT
The "real men" isn't intentionally sexist. It's tongue-in-cheek. Ever heard of 1982 book "Real Men Don't Eat Quiche" (http://en.wikipedia.org/wiki/Real_Men_Don%27t_Eat_Quiche) or the famous article "Real Men Dont Use Pascal" (http://practical-tech.com/entertainment/real-men-dont-use-pascal/ )?
Sign in to Reply
jlcsa
8/18/2009 1:17 PM EDT
Dear Mr. Barr, I am an embedded software developer for the Canadian Space Agency. C is our language of choice. I am not sad to see Assembly go, but it will always remain useful in certain situations. The only reason we won't go for C++ is as D_Lundin mentioned: lack of fully-compliant compilers.
Just wanted to say I appreciated reading your article.
Sign in to Reply
Bill E
8/20/2009 8:54 PM EDT
I disagree that "macros .. are not fixed in C++."
Template functions take care of the vast majority of cases where one would be forced to use a macro in C,
in both a more typesafe manner and without the dreaded namespace pollution of macros.
As for efficiency, you generally don't pay for what you don't use - although you may need to tell the compiler to not generate code for exception handling and/or RTTI if you truly can't afford them. That said, I've found that it's the programmer, not the implementation language that drives an application's ultimate efficiency.
I'm curious about the reference to security as a potential downside of constructors. On the flip side, I'd argue that C++ features such as constructors can increase the safety of code [see http://hissa.nist.gov/sw_develop/ir5769/ir5769.l.html], to ensure that variables are initialized to a reasonable state. And C++'s destructors allow one to implement RAII, virtually eliminating the chance of resouce leaks - here I'm referring to not just memory leaks, but "leaks" of mutexes as well.
Sign in to Reply
D_Lundin
8/21/2009 8:35 AM EDT
Regarding macros:
While there are better ways to solve things in C and C++, macros are still allowed. The only reason to use macros in ISO C 9899:1990 is portable inlining of functions, a minor concern as modern compilers handle this automatically.
In C99 and C++ I can't think of a single reason to use them. Yet people use them a lot, because they don't know better. There is a tendency of thinking "the language allows it so it can't be bad", or worse: "the language allows it so I'm gonna use some alien, impossible-to-interpret syntax to show off my syntax knowledge".
Regarding constructors:
In safety-critical systems, it is considered poor practice to rely on initialization values. This isn't because of the language, but because of the unreliable nature of RAM. In such systems, there could be days, weeks or years from the point of initialization to the point where the variable is used. If you rely on the initialization values, you leave the safety in the hands of the RAM manufacturer. If you instead leave the initialization constants in NVM as long as possible and set variables in runtime, before they are used, you get increased safety.
Also, in typical safety-critical systems you have no memory leaks at all, as dynamic allocation and heap usage is completely banned. Mutex leaks aren't too common either, as threads/processes tend to exist during the whole program execution. Anything getting created & deleted dynamically is a potential hazard.
In non-critical systems, there are typically no policies for the above and programmers are left to goof around with the RAM as they see fit. Hence the need of various design patterns, smart pointers etc in such systems. I would whole-heartedly agree that constructors/destructors will increase safety drastically in any system allowing dynamic resources.
Sign in to Reply
Dan_Saks
8/21/2009 10:14 PM EDT
As I have written in the past, I believe C++ is generally preferable to C for most applications, embedded or otherwise. I believe that some of the remarks in this thread recommending C over C++ are mistaken. See the details in my latest column at http://www.embedded.com/columns/programmingpointers/219401085
Sign in to Reply
DonDiegoDelaVega
8/27/2009 11:30 AM EDT
I remember when the phrase was "Real men program in assembler"! In my experience embedded applications fall into one of two categories, timely real-time and time critical real-time, the difference being 100s of Msecs response time to 100s of Nsecs response time. There should be no question that using OOA/OOD is the standard operating procedure used for program design, even for embedded systems. In most of todays embedded designs we have the luxury of megabytes and gigahertz verse the kilobytes and megahertz available 15 years ago in our embedded targets. Given that, I say that C++ would be my choice for timely real-time applications and C for time critical real-time apps. This is because the designer not the compiler has complete control over fixed verse dynamic memory allocation and other things that go on under the hood of C++. A couple a years ago I was told by a Wind River FE that they once implemented VxWorks in C++ but had to replace it with a C version for timing reasons. I strongly believe that a disciplined designer can use OOA/OOD in their C designs (i.e. a collection of procedures that perform a function or service (class) in a single module, constructors, destructors, etc.). I admit that C may not be the only language for time critical real-time apps but currently has the most development environment support for the widest range of target systems. If you check out the leading tool vendors such as Wind River, TI and Matlab, I think you will see what I mean.
Sign in to Reply
S.T.
8/31/2009 8:34 PM EDT
Paraphrasing somebody's comment on Reddit I would say: "Real men produce good and complete system analysis before starting to program with the most appropriate tool."
A good system analysis makes abstraction of the tools used to implement the system. OOD/OOA are not part of this phase but of the next step which is software architecture and design. If the analysis suggests an important degree of repeatability then an OO approach may be chosen. If not SADT or similar techniques will do it.
Good examples are: WIDOWS OS, structural approach in C. MSFC, OOA/OOD in C++.
Any other approach which bypasses the system-analysis and jumps directly to low-level software design will produce unpredictable results and cannot be cited as reference.
IMHO the C/C++ controversy is just another "religious war" without any real support. Ultimately the common-sense and the market decide. Just as an exercise for all OOA/OOD fans out there: please look up and let me know one popular, widely used OS based on this technology, an OS being the perfect example of an embedded system.
Sign in to Reply
sagedeep
9/8/2009 6:03 PM EDT
Real engineers get the requirements, design, select the right tools and solve the problem. When is the last time you changed the oil or spark plugs with a pair of pliers? You can probably do it... but why? Right tool for the job, move on!
Sign in to Reply
leblanc meneses
9/14/2009 12:43 PM EDT
how do you unit test?
I believe higher level languages help you prototype faster your algorithms and have built in unit test tools ike: junit, nunit, mstest.
while i united tested my c code using bash and running different test executables.. a testrunner like those listed above improves speed in development.
http://robusthaven.com/products/Parsing+Expression+Grammar
hence my company is working on a way to convert msil to glib like system.
this is no different on how labview uses graphical environment and generated c code to be compiled by keil tools to target arm.
Sign in to Reply
typhillips
9/15/2009 4:17 PM EDT
A very refreshing article to read, which confirmed my suspicions. I keep reading articles about the "rise of C++" in embedded development and I just didn't buy it.
DonDiegoDelaVega wrote:
"There should be no question that using OOA/OOD is the standard operating procedure used for program design, even for embedded systems. In most of today's embedded designs we have the luxury of megabytes and gigahertz verse the kilobytes and megahertz available 15 years ago in our embedded targets."
Although this is certainly true in some situations, this is a bit of a generalization. I work for an industrial controls manufacturer that ships hundreds of thousands of units per year. Cost is extremely sensitive and even a difference of a few dollars per unit has a substantial impact on the bottom line. Thus, we are often left with less CPU power, program ROM and RAM than in an ideal situation. There is no way our existing firmware design could be adapted to C++ without a significant effect on system resources.
D_Lundin, your comments are excellent regarding the better suitability of C for real time embedded systems. You had a number of excellent, spot-on points. I did have a comment about one remark you made:
"While there are better ways to solve things in C and C++, macros are still allowed. The only reason to use macros in ISO C 9899:1990 is portable inlining of functions, a minor concern as modern compilers handle this automatically."
The compilers might handle inline functions, but if you need to write strictly ANSI-C compliant code you are out of luck. We follow the MISRA-C (1998) standard for critical real time systems and it strictly prohibits any non-ANSI compliant code. For this reason we do use macros, although any new ones that we define are looked at very closely during code walkthroughs in our Design Review meetings.
But yes, you are right. Macros are very dangerous. When in doubt, parenthesize. :)
Sign in to Reply
typhillips
9/15/2009 4:42 PM EDT
I should clarify my last statement slightly. The MISRA-C 1998 standard used by my company (already outdated I should mention) merely states that "all code shall conform to ISO 9899 standard C, with no extensions permitted".
The question, I suppose, is which ISO 9899 standard? As I understand it, inline functions are included in the ISO 9899:1999 standard, which pre-dates the MISRA-C 1998 standard.
Sign in to Reply
KarlS
10/29/2009 2:31 PM EDT
The points you made are quite interesting. The proliferation of micros is one indication that the one memory with a few registers architecture is the underlying problem. A lot of programming practice evolved from the days when memory was the most precious system resource. Single chip embedded systems don't utilize the hundred or so memory blocks that are available on chip because of this inheritance.
So, where am I going? We can put all the variables in a memory as registers. We can have separate memories for statement and operand processing. The variables are all the same width, etc. and all the memories can function in parallel with huge bandwidth while simultaneously using minimum clock cycles to do the function. Realtime capability is maximized.
Now, how do we program the chip? With a subset of C that has the embedded no-nos left out. Where do we get it? Use the string manipulation in C#, take the C expressions (strings that end with a ';'), parses them and generate the memory data. Now take a few classes and clock their behavior emulating chip clocks and output a cycle by cycle activity so the user can see the variable values as they are changed and the flow in the hardware. The user can control function call protocol, memory allocation options etc either by setting options or modifying the parser.
Sounds far-fetched, but I have a prototype running.
Sign in to Reply
eAnimesh
11/5/2009 3:38 AM EST
Language is medium to express the desired getting done from machine. C is the obvious as the most practiced language through out the world. If we have alternatives for the end client, we are free move on with more than languages to environments like Java, .net, and many more to offer RAD in future but the core of all remains the same...
we always love short cuts :-)
Sign in to Reply
returningTarzan
11/5/2009 12:39 PM EST
> Horrible, unnecessarily complex syntax. C++ is perhaps the least readable programming language of them all. Compare the syntax to Java or C# and you will grimace at the C++ syntax.
The same could be said of C compared to so many other languages. All the brackets and special characters and ^ when you really mean XOR, and % when you mean MOD? And why does "static" mean two different things depending on the scope? It's a matter of getting used to it.
> Potential for very inefficient programs through inheritage, templates, STL etc. STL classes will enforce a heap when we don't need/want one.
This is a rubbish excuse for being a dinosaur. :) Yet it is one of the oft cited reasons for rejecting C++: you can write inefficient code with it. So what? The same is true of C if you compare it to assembler. High-level abstraction means you're not constantly face to face with machine code, so how do you really know that the compiler is doing?
int i;
some_type array[ 10 ];
for( i = 0; i < 10; i++ ) array[ i ] = 0;
vs.
int i;
some_type array[ 10 ];
some_type *iter = array;
for( i = 10; --i; ) *iter++ = 0;
*iter = 0;
vs.
some_type array[ 10 ];
some_type *iter = array;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter = 0;
vs.
some_type array[ 10 ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
vs.
some_type array[ 10 ];
array[ 0 ] = array[ 1 ] = ... = 0;
And so on. Which would you say is the version that C most encourages? And which is the more efficient? I assure you, they don't all compile to the same code in any compiler I've come across. Bottom line is, whatever language you use, there is always the potential to write code which is very inefficient. No language can write efficient code for you.
However, while C++ allows you to do all the exact same things you can do in C (thus letting you write a C++ program which is exactly as efficient as the next guy's C program) it opens up the door to a whole new class of optimisations that strictly-C programmers can rarely even conceive of.
Some seem to come at a performance cost but more often end up speeding up your code by making it a lot simpler, removing special cases and redundant copies. Boost's shared_ptr is a good example of that.
Others simply enable you to try out more things because your job is so much easier. Imagine a C program which near its core has a linked list of structures. You've painstakenly written 25000 lines of code that make use of that list, but then you realise that your CPU has a data cache and you'd be much better off replacing the list with an array. How motivated would you be to make the change? Then imagine the same thing written in "clean" C++, where all you need to do is replace the list with an array, and standardised container interfaces make sure your code still works the same.
The point is you're way oversimplifying things by suggesting C++ code is inefficient at all compared to C code. A competent C++ programmer will typically write fast, efficient code in less time than a competent C programmer, and in addition the C++ programmer's code will be more maintainable and easier to optimise further.
> C++ programs are very hard to port.
This concern is genuine, as is the concern that C++ has failed to standardise common datatypes, making code reuse and collaboration much more difficult than it could have been.
(Of course, the equivalent constructs in C are not standardised, either, they just rarely exist at all because they're so difficult to work with, so the problem is smaller.)
> The only part of object orientation that is a must-have in embedded systems is private encapsulation.
Seriously? What about multiple instances of all that privately encapsulated functionality? When someone goes and adds another UART to the system, do you copy your uart1.c to uart2.c and do a search/replace on all globally exposed symbols? What if UART2 behaves slightly differently from UART1? That's a perfect candidate for inheritance (with or without the overhead of virtual member functions). What about a component which is exactly identical to another component, except data words used throughout are 16 bits instead of 8 - template metaprogramming to the rescue.
For embedded software in particular, C++ is the PERFECT compromise of object-oriented possibilities, metaprogramming options, and low-level versatility and efficiency. Sure, there are promising new languages like D, but D is still in its infancy and not yet widely supported.
> Also, the most moronic ingredients of C, like for example macros and the way integers are implemented, are not fixed in C++
Macros were not fixed with C++, no, but they were made obsolete. Use inline functions instead, and templates if you want variable type support. Here's a generic swap function, for example:
template
inline void swap( T &a, T &b ) {
T temp = a;
a = b;
b = temp;
}
As for integers, I assume you mean the loosely defined sizeof( int ). Yes, C++ does not address the problem, but you can typedef your way out of it just as you can in C. In fact you can include the exact same header file.
Now, it's true that STL really wants new/delete (and therefore a heap system that provides malloc/free), but you don't HAVE to use STL. C++ is flexible enough that you can write your own containers suited for your particular application. You can write your own memory allocators (or rely on the stack and/or static data), your own smart pointers, your own pooled string class, and whatever. You can even do reallocateable objects using smart pointers if you're afraid of fragmentation.
It's a strange myth that constructors are a security risk. I guess they might be to a developer who counts ensuring proper initialisation of data as a security risk. But in such a case the real security risk would be the developer in question. Innit.
In my experience most embedded developers are not educated programmers, in fact they rarely qualify as good programmers (not that educated = good, but whatever). They come either from an engineering background (having been taught in the 70s or 80s something you might still call "programming"), or they're completely self-taught. Either way they tend to have far too high an opinion of themselves and are completely out of touch with computer science.
The most seriously retarded programming I've seen has come from the embedded industry. I'm tied down by NDAs, but suffice it to say even something as crucial as the encryption on bloody cash handling units is more often than not implemented by complete idiots. Yes, swapping two bytes around in a key gives you some sort of security (sigh), but swapping them back again does NOT double that security. Honest to God, that's a real-life example.
Sign in to Reply
Lundin
11/6/2009 6:31 AM EST
> "This is a rubbish excuse for being a dinosaur. Yet it is one of the oft cited reasons for rejecting C++: you can write inefficient code with it. So what? The same is true of C if you compare it to assembler. High-level abstraction means you're not constantly face to face with machine code, so how do you really know that the compiler is doing?"
The real issue here is the vast amount of incompetent programmers out there. If the language allows something, you can be sure they will use it. This is why we need standards like MISRA that point out what you should avoid. Now when there is a MISRA C++, perhaps there is hope. Hopefully it will become as widely recognized as MISRA-C.
> "for( i = 0; i < 10; i++ ) array i = 0;"
This isn't really a good example, as it is hardware-related and not language-related. The reason no compilers will compile that the same way is because the efficiency depends heavily on the structure of the CPU. A compiler for a tiny 8 bit micro will no doubt optimize to a downcounting loop because compare against zero is usually more effective. While a 32-bit Intel PC compiler might optimize based on how the internal cache memory looks like. So there will be completely different decisions based on CPU architecture.
Templates, inheritage etc on the other hand, will by their nature enforce an amount of overhead algorithms no matter hardware. You cannot design inheritage without a certain amount of overhead code, by its nature. Simply: a code without overhead will be more effecitive than with that comes with overhead.
> "Others simply enable you to try out more things because your job is so much easier. Imagine a C program which near its core has a linked list of structures. You've painstakenly written 25000 lines of code that make use of that list, but then you realise that your CPU has a data cache and you'd be much better off replacing the list with an array. How motivated would you be to make the change? Then imagine the same thing written in "clean" C++, where all you need to do is replace the list with an array, and standardised container interfaces make sure your code still works the same."
As I wrote in some earlier post, I never questioned the usefulness of modular, object-oriented programming: this is a must. The above is based on the faulty assumption that you cannot write modul-based code in C. The little "class" keyword doesn't do that for you, it is all about your program design. It is quite possible to goof up that linked list in C++ as well. If you have written a linked list code module in C like the one you describe but cannot replace it, it is because you didn't write it as an autonomous code module. This isn't related to the language but to the programmer's design skill.
> "A competent C++ programmer will typically write fast, efficient code in less time than a competent C programmer, and in addition the C++ programmer's code will be more maintainable and easier to optimise further."
I don't agree at all. I would label myself competent in both languages, at least I have worked with both languages for 10 years. I am much more effective in C. Because after the program design is done, I can simply write down the program in C, focusing on the sole purpose and functionality of the program without any headache. The same program in C++ will always give you extra work. You end up like this:
"Oh I notice I must use a destructor here. Ach, then I'll need to implement a copy ctr and an assignment operator too. Oh wait, I will need to do this for the inherited class as well. Wait, what will happen with that constructor when I inherit the class. I must fix it... and that copy ctr as well."
At least 50% of your time goes to meta-tasks like that, instead of investing the time in your actual functionality. And that is without templates. Don't get me started about STL... I have never been productive while writing STL code, and it is a real pain to maintain because the STL library has a real talent for making any simple code turn incredible complex, and often buggy because of it.
> ... "When someone goes and adds another UART to the system, do you copy your uart1.c to uart2.c and do a search/replace on all globally exposed symbols? What if UART2 behaves slightly differently from UART1? That's a perfect candidate for inheritance (with or without the overhead of virtual member functions). What about a component which is exactly identical to another component, except data words used throughout are 16 bits instead of 8 - template metaprogramming to the rescue."
This is a very common situation. If you made the original routine with careful design, you would allow it to expand into an array of chunks of private data and let the caller run the functions like:
uart_init(UART1, ...);
uart_init(UART2, ...);
uart_send(UART1, ...);
uart_send(UART2, ...);
where your uart code module looks like:
typedef enum
{
UART1,
UART2,
...
} UART_TYPE;
static uart_data [X];
void uart_init(UART_TYPE type, ...)
{
init(uart_data[type]);
}
Inheritance would typically be fixed with function pointers. For example, the uart_send routine may call upon different functions depending on which uart that was used.
The advantage of the above is that I can write that code in 10 minutes. Good luck writing the same implementation with class, templates and inheritance in that time. No, we suddenly talk about one day of work in C++, for the same result in the end. Both the C and C++ solution will likely be as easy to maintain, but the argument for C here is productivity and time to market.
> "Macros were not fixed with C++, no, but they were made obsolete. Use inline functions instead, and templates if you want variable type support."
This was already discussed in this thread or the other... C supports inlining as well.
> "Now, it's true that STL really wants new/delete (and therefore a heap system that provides malloc/free), but you don't HAVE to use STL. C++ is flexible enough that you can write your own containers suited for your particular application. You can write your own memory allocators (or rely on the stack and/or static data), your own smart pointers, your own pooled string class, and whatever. You can even do reallocateable objects using smart pointers if you're afraid of fragmentation."
You can do that in most languages. I've written smart pointer implementations in C for example. I see no real advantage/disadvantage for C++ here.
> "It's a strange myth that constructors are a security risk. I guess they might be to a developer who counts ensuring proper initialisation of data as a security risk. But in such a case the real security risk would be the developer in question. Innit."
This was also discussed earlier, it is not the initialisation itself that is dangerous, but the way data gets corrupted in RAM over time. So the problem itself is a hardware-related one. Avoiding static initialisation is part of defensive programming, and is widely practiced in the automotive & aerospace industries.
> "In my experience most embedded developers are not educated programmers, in fact they rarely qualify as good programmers (not that educated = good, but whatever). They come either from an engineering background (having been taught in the 70s or 80s something you might still call "programming"), or they're completely self-taught. Either way they tend to have far too high an opinion of themselves and are completely out of touch with computer science."
I completely agree, this is a huge problem for the industry.
Sign in to Reply
returningTarzan
11/6/2009 11:22 AM EST
> The reason no compilers will compile that the same way is because the efficiency depends heavily on the structure of the CPU.
b;
a( new Foo( ... ) ); // create a Foo and point to it
I actually meant, those five examples will compile differently on the same CPU. Even though they express the same operation, they are not equally efficient, and there is no immediate way to tell from just the C code which is more efficient. So you need some knowledge of how a C compiler translates code in order to produce efficient code with it, just as you need some knowledge of C++ and its relationship to the lower-level compiler output before you can be efficient with C++.
> A compiler for a tiny 8 bit micro will no doubt optimize to a downcounting loop because compare against zero is usually more effective. While a 32-bit Intel PC compiler might optimize based on how the internal cache memory looks like. So there will be completely different decisions based on CPU architecture.
And this is another advantage of higher-level languages - you move from telling the compiler how to do things further towards telling the compiler what you want to do, giving it more room to fit your code to the target platform. This advantage is greater in C++, and greater still in even more high-level languages like D (with the "foreach" construct etc.).
By the way, in the case of "for( i = 0; i < 10; i++ ) array[ i ] = 0" (how do you escape angled brackets on this forum?) the compiler probably wouldn't change to a count-down loop, since you're explicitly telling it in what order to clear the array. It won't reorder anything since that would leave the array in a wrong state if say an interrupt occurs. Of course if it creates a pointer to iterate over the array, the "i" disappears from the body of the loop, and if you're not using i anywhere after the loop, the compiler just might get it right. But the point is if you don't get all those assumptions right you're writing inefficient code, so it's not as if C safeguards against that, even if you use exactly the approaches the language seems to encourage.
> You cannot design inheritage without a certain amount of overhead code, by its nature.
You can, though. Inheritance just means you're sharing code between classes. If the specific class is implied when you call a member function there is zero time spent checking whether you're calling a base-class member function or what derived class the call should go to.
When using virtual member functions you have the option of calling the base class and having the call automatically routed to the correct one of several derived classes. That comes at a cost, but the cost is precisely that of looking up a function pointer, which is precisely what you'd use to get the same behaviour out of C (except the compiler has the option of converting to switch type constructs if that should happen to be more efficient).
In fact, inheritance tends to produce smaller code because you're given a good framework for code reuse (within a project - again, C++'s lack of standardised classes compared to Java etc. complicates code reuse between projects, this is true). For instance if you have that SerialPort base class, you will put shared functionality into the base class, and functionality specific to an RS232 into the derived RS232 class, and anything specific to RS485 into the RS485 class. In my experience embedded applications are packed with cases where precisely that type of code reuse is perfectly suited.
> At least 50% of your time goes to meta-tasks like that, instead of investing the time in your actual functionality. And that is without templates. Don't get me started about STL... I have never been productive while writing STL code, and it is a real pain to maintain because the STL library has a real talent for making any simple code turn incredible complex, and often buggy because of it.
I've never found those meta-tasks to be painful. And it's fruitful labour, too. You can just ignore the copy c'tor if you know you're never going to use it (or if the automatic one is good enough). If you are actually going to be copying objects, it's not really a meta-task, but a process of defining what an object is if it's a copy of another object (which is not a trivial thing at all so should get some attention whatever language you're in).
There is some overhead in that you sometimes do need to put more planning into your code when you use more advanced features. But the extra effort put into a more OO solution really, really, REALLY pays off in the end, at least such is my experience. Iterators are a pain in the neck, but they do make sense, and they are a very useful tool when they're called for.
I'm currently maintaining a pure-C project which was written with precisely the philosophy you describe. Someone was way too quick to start typing in "actual functionality", and the result is, well, the mess you could expect.
Of course I share your frustration with STL sometimes (I think all C++ coders do), but then I just don't use it when it doesn't offer me the functionality I'm looking for, or the complications outweigh the benefits. And the point especially when you're making a comparison to C is that with C++ you can either use STL, use Boost, create your own framework classes, or fall back on plain-C approaches.
> The advantage of the above is that I can write that code in 10 minutes. Good luck writing the same implementation with class, templates and inheritance in that time. No, we suddenly talk about one day of work in C++, for the same result in the end. Both the C and C++ solution will likely be as easy to maintain, but the argument for C here is productivity and time to market.
But, that example is not a complicated thing in C++ at all.
class UART {
public:
UART( ..arguments.. ) { ..common constructor bits.. }
virtual void send() = 0;
};
class RS232_UART : public UART {
public:
RS232_UART( ..arguments.. ) : UART( ..passed arguments.. ) { .. RS232 constructor bits .. }
void send( char c ) { ... }
}
class RS485_UART : public UART {
public:
RS485_UART( ..arguments.. ) : UART( ..passed arguments.. ) { .. RS485 constructor bits .. }
void send( char c ) { ... }
}
.
.
RS232_UART myPort( ..arguments.. );
RS485_UART myOtherPort( ..arguments.. );
myPort.send( 'a' );
myOtherPort.send( 'b' );
doSomethingWithThis( myPort );
.
.
void doSomethingWithThis( UART& port ) {
// This function can send() to port not caring what subclass it is
}
(Plus some optional finetuning like making the UART constructor protected, etc. etc.)
And now you've defined precisely what you want to do. This will implicitly use function pointers in doSomethingWithThis() to find the right class for &port, and where the class is known in the scope, will call the right version of send() directly, automatically tied to the right set of member variables.
Your example left out the structure of the init() function and how you need to switch between different UART_TYPEs all over the place. Not only does switching quickly become less efficient than vtable lookups, you'll have to do it in any place that the functionality of one serial port differs from another.
So think about maintainability: When an RS422 port is added to the mix, in the above you just add another class. When there is no longer a need for RS232 support, you can simply remove the RS232 subclass (actually the compiler does it for you when it's no longer referenced), and the code to deal with it doesn't bloat up the application anymore.
Also, where your code has a single uart_data structure to deal with all types of UARTs, the above approach would not waste space on member variables that are needed for one class of port and not the other.
The class hierarchy reflects a logical hierarchy of UART functionality. The use of objects reflects the layout of the system. What could be easier or more natural to work with? Plus, it's as efficient as a plain C approach (if not moreso) and way easier to maintain.
This project I'm maintaining at the moment has a dozen serial ports, each slightly different to the next, and they're done in exactly the way you describe. No differentiation between types and instances, loads of variables exposed to the global namespace, horrid repetition of code (i.e. bloat and poor maintainability), no logical grouping of code and related data, and so on. OO would have greatly simplified the whole thing and C++ would have greatly simplified the OO.
> C supports inlining as well.
I know. I don't consider inlining an advantage of C++, but rather an example of why macros are redundant in both C and C++. They are more redundant in C++ because of templates, though.
> I've written smart pointer implementations in C for example.
How? C doesn't provide mechanisms to guarantee that code is called when a variable leaves scope or when memory is released. And you don't have operator overloading and such. Consider Boost's shared_ptr for example:
{
shared_ptr
{
shared_ptr
a->something();
b = a; // b points to the same Foo
}
a->something(); // wouldn't work because a is out of scope, but..
b->something(); // b still points to the object. So who owns the Foo then?
}
// Ha! Doesn't matter, because b was the last reference, so now the Foo has been
// automatically destroyed. I'm immune to memory leaks, mwhahaha!
Yes, you can do some sort of reference counting in C, and you can have some sort of ownership concept, but an actual smart pointer?
{
Foo *b;
{
Foo *a = (Foo*) malloc( sizeof( Foo ) );
b = a;
}
something( a ); // wouldn't work because a is out of scope
something( b ); // would still work
}
// But now we have a memory leak. How are we supposed to conceptualise the lifetime
// of the Foo structure? How do we know that nobody is referencing it anymore, and how
// do we turn the disappearance of the last reference into a call to free()?
> Avoiding static initialisation is part of defensive programming, and is widely practiced in the automotive & aerospace industries.
Sure thing. I avoid it like the plague. But I didn't catch how it relates to constructors?
Sorry for the endless ranting, BTW. I'm just a little bored, you see. ;)
Sign in to Reply
returningTarzan
11/6/2009 11:30 AM EST
On a side note, I hate forums that strip anything that looks a bit like an html tag. ;)
Sign in to Reply
KarlS
11/6/2009 11:53 AM EST
Before you get too carried away badmouthing what has evolved to the point where geniuses like you are now involved, remember those were the ones that made it work while others were off inventing computer science. They had a job to do and not the luxury of waiting for computer science to mature.
I would sure like to see the hardware that you designed. Also in your spare time would you whip up a hardware simulator that can be used to check out functional behavior in the early stages of design? Or do you just write code and run it with no debug and expect hardware design to be done the same way?
One last thing. Since the compiler does whatever it wants, how do you know if code execution time meets the hardware timing requirements?
Sign in to Reply
returningTarzan
11/7/2009 9:04 AM EST
"Before you get too carried away badmouthing what has evolved to the point where geniuses like you are now involved, remember those were the ones that made it work while others were off inventing computer science. They had a job to do and not the luxury of waiting for computer science to mature."
I respect programmers from 20 years ago who didn't have modern tools at their disposal. I WAS a programmer 20 years ago. (And back then I did many of the things I would now consider bad programming, sometimes out of necessity, sometimes because I just didn't know what the h I was doing.)
The point is I move on and TRY to stay up to speed. A doctor who still runs around amputating limbs because he never trusted antibiotics is just a bad doctor. It doesn't matter if we're talking about the guy who invented the bone saw, I still want the doctor with the antibiotics to treat my infection. And in 20 years I'll want the guy who knows how to operate the germ-zapping quantum laser.
But it's all completely irrelevant to the fact that the myths about C++ prevalent in the embedded community have very little truth to them.
"I would sure like to see the hardware that you designed. Also in your spare time would you whip up a hardware simulator that can be used to check out functional behavior in the early stages of design?"
And this I think goes a long way towards explaining where those myths come from.
"One last thing. Since the compiler does whatever it wants, how do you know if code execution time meets the hardware timing requirements?"
A C++ compiler doesn't do whatever it wants. It does exactly what you tell it to do, but compared to C, C++ gives you a larger vocabulary with which to communicate those intentions. You're still free to fall back on just the C subset of C++ when some of that automated (not spontaneous) code generation could cause unpredictable timings. You're even free to include a bit of inline asm where you feel it's appropriate.
Again, a plain-C compiler will still do things you might not expect if you don't know what you're doing. For instance, does this cause a delay?
int i;
for( i = 0; i < 1000; ++i );
Does this allow you to detect an array overrun?
int array[ 100 ];
int overrun_check = 0;
some_difficult_function( array );
if( overrun_check ) ...
In both cases an asm-accustomed programmer with little knowledge of C might not understand how the compiler optimises stuff away and automatically lays out variables on the stack. A C compiler can insert code, too. Just use floats on any system that doesn't have an FPU, and count yourself lucky if the compiler warns you that all the float math is really being emulated in integer arithmetic.
Bottom line is, if you don't understand the tool you're using, the results may surprise you. If you do know C++, however, there is no mystery to it. It only automates operations, it doesn't have a mind of its own.
Sign in to Reply
returningTarzan
11/7/2009 9:05 AM EST
Where did the BBcode come from? :( I suck.
Sign in to Reply
Lundin
11/16/2009 10:54 AM EST
Ok I cannot muster enough energy to debate this futher, but I found an amusing detail related to this discussion from another article on this site, namely the one regarding a publication "Software for Dependable Systems" found here:
http://www.embedded.com/columns/breakpoint/220900315
Note that the book mentioned solely addresses safety-critical systems, and thus not generic embedded apps. This book is written by a committee consisting of numerous experts. They address a number of "best practices", where they explicitly warn against inheritance:
"Inheritance is a powerful but dangerous programming feature. Use it sparingly, and whenever possible favour composition (adding functionality by embedding one object explicitly in another) over inheritance. Design for inheritance or prohibit it, and do not extend classes that were not designed with extension in mind. In critical applications, avoid inheritance or ensure that adequate time has been allowed for the extensive additional verification activity that will be required."
This is an interesting opinion. As I wrote in my previous post, I mainly avoid inheritance for complexity, productivity and performance reasons. I have not really regarded it as a potential hazard before, but I guess it is all related. Inheritance adds complexity and program dependences, two factors that the book point out as common causes of disasterous software failures.
The most interesting about this remark is: Just because C++ has a feature that C lacks, it doesn't automatically mean that this feature is equivalent with good program design. It may very well be the opposite. This is what I've been preaching throughout this discussion. Good program design is in most cases language independant.
Sign in to Reply
SoftWare Engineer
12/16/2009 8:46 PM EST
Every languages have the lacks of itself.But I think fit the field is great.
I can't say the C is greater than C++ or assembly.But I can say ,write the bootloader need the assembly at the start ,need the C at the stage 2 of bootloader.And need the C++ development some Tools in windows platform debug and test the embedded system,and need the C++ write the QT GUI.
So I think the everything is absoluty perfect.Because a matter apperanced have its principle. We use them in a fit fied that excellent.
Sign in to Reply
SoftWare Engineer
12/16/2009 8:53 PM EST
Sorry. everything is not absolutely perfect.
Hans
Sign in to Reply
pra280
1/14/2010 9:25 AM EST
returningTarzan
Software Engineer :Experience in C,C++ is different issue.
tell me
void myFunc()
{
int x=10;
static int rem=x;
}
Whts worng with
static int rem=x;
A real time programmer not only know the how his code looks or occupy the machine length, what amounts of time to take execute(in CPU Cycle), maintain the code.
So forgot about C++ you all are high level programmer and you cannot understand.
Pravas R. Mohanty
Sign in to Reply
Code Monkey
5/12/2011 3:44 PM EDT
Three points:
1. The lines on the graph sum to about 90%. What languages comprise the other 10% and why are these languages chosen over C/C++?
2. C++ is not C. It just happens to have C's syntax. It will take a while for embedded guys to migrate their thinking, and their programs are often small enough to not need encapsulation.
3. Productivity studies between scripting languages (Perl/Python/Lua) and classical languages (C/C++/Java) have shown a 2:1 difference. C++ only gilds the turd.
Sign in to Reply
jimeffect
3/19/2012 4:32 AM EDT
C has had a profound effect on the computing world, and even as more languages are invented, it still remains high on the preferred choice of languages to program in for most programmers. I don’t see that changing anytime soon, unless a really superior alternative that is easy to pick up comes along.
Jim - http://www.effectwebagency.com
Sign in to Reply
GordonScott
3/20/2012 11:42 AM EDT
As so often one person's embedded is not another's.
Embedded ranges from 6-pin PIC processors with a few hundred instructions and a few bytes of RAM, through smart-phones and iPads to, for example, multi-board VME-bus machines with multiple multi-core processors per board.
Just like real-time programming varies from getting the data away before the EMP hits, to payroll.
If using C for embedded more than other languages makes me more Real and less Virtual, I guess that's a plus :-)
Gordon.
Sign in to Reply
tilmann
3/21/2012 9:59 AM EDT
Questioning which language is the biggest part of a software project is just crazy:
1. It is like asking what is the biggest amount of foods in chili con carne: definitely not chili! In my software projects assembly language is VERY important, but from number of lines definitely the smallest part.
2. People that have learned assembly language and control bit operation and event-driven programming easily can write C programs, but not vice versa!
3. I see very often how much problems only-C "programming" people have:
- they cannot differentiate between inner loops and other stuff
- they cannot really program in fixed-point arithmetic: e.g. they just do not understand why to make averages with 8 instead of 10 values and why not divide by 8 for the average of 8 values and why not shift right by 3 bits instead of dividing and why doing nothing is the best - resolution of the result is 8-fold better, run-time and energy consumption is zero
4. An assembly programmer loads multiplicand and multiplicator in an hardware multiplier and takes the high word as result - no shift operations, no type casting, ...
A lot of teachers tell they would teach "programming". Most only teach some coding. On my programs coding takes only about 10 percent of programming time and the decision in which languages which parts will be coded (and which parts will finally taken over by hardware in embedded systems) is often done after 70 to 80 percent of development progress.
I understand that in many countries most people learn only one language, e.g. American English. Can anyone tell my why this should be an advantage?
Sign in to Reply
De Designer
4/5/2012 10:50 AM EDT
For me, am a Newbie. Please somebody should help and take me along. Thanks great men.
Sign in to Reply