Most embedded projects employ C or C++ although many C++ applications are little more than slightly extended C applications. Actually, C being the dominant programming language for embedded applications is not surprising. It is often the only alternative at the low end of the spectrum where 8- and 16-bit micros dominate. Higher end 32- and 64-bit developers have a choice of almost any programming language and the mix being used reflects the options available. Still, there are many that utilize only C on these platforms.
I don't expect to change many minds that C isn't the best thing since sliced bread and I actually use C a good bit. In fact, I've used C almost since it showed up. I actually started with Basic and assembler and then progressed to Fortran and Cobol. I even dabbled in Algol and Snobol. You will probably have to look those up on Wikipedia.
C is great because of its simplicity. Embedded C programming can even be taught using platforms like Arduino (see Arduino Expands Into More Demanding Applications). Some even teach it as the first programming language in schools and colleges although C++ seems to be taking on that challenge these days.
Still, C is one language that it is all too easy to shoot oneself in the proverbial foot. Using any programming language can lead obscure programming problems but C leads the way. This is especially true when dealing with pointers where bad programming practices abound.
Now I will admit that I have done my fair share of doing everything wrong with C like using special values for pointers to mark exceptions. And about those crazy casts. Sometimes you have to do these things to get around limitations of a compiler or to get something to work with I/O on a microcontroller.
It usually comes down to "It's ugly but it works."
Much of this comes down to using plain C with a compiler, linker and debugger. These are all the tools a developer needs. Isn't it?
Personally I think embedded C programmers should take a closer look at Ada. It is close to C in architecture and the upcoming version includes supports contracts. You can download Adacore's GNAT Pro Eclipse-based IDE and tool set for free. I highly recommend it.
Of course, learning yet another language is at the bottom of the list for most programmers except possibly me. So what do to?
At least turn to some static analysis tools to improve your programming environment. Remember, fixing a bug becomes exponentially more expensive as time goes on. What goes wrong today will be harder to fix if you find it tomorrow or, worse, when the project has been in the field.
Those who read my stuff me regularly know I harp on tools and debugging all the time. I don't get a lot of programming time these days but I have been playing with MISRA C (see MISRA C: Safer Is Better) via IAR's Embedded Workbench. One of the options available is MISRA C (Fig. 1) and trying to work within its confines does change the way you write code. It is usually for the better.
One of the harder things to deal with in MISRA C is pointers or the lack there of. It tends to be a mindset change but this is true of moving to Java where you have references but not pointers. Try functional or logic programming if you want to really bend your mind.
There is a reason that developers needing safe and reliable software use tools like MISRA C for applications such as automotive and transportation. It is not a crutch but an extension of the compiler that won't let you do whatever you want either. I can't figure out why programmers don't want to use tools like this but some don't. On the other hand, you couldn't take it away from most developers who have been using it for any length of time. It is actually frustrating switching to another IDE that doesn't have MISRA C support.
MISRA C tends to be the tip of the iceberg when you start looking in that direction. Static and dynamic analysis tools are the norm in enterprise and safety oriented application areas like avionics. Still, for the microcontroller developers, the tools exist. Take LDRA Tool Suites as an example. It has Microchip MPLAB integration (see Software Verification Targets Tiny Micros).
LDRA's features make MISRA C look like a tinker toy. I won't even get into life cycle management or requirements traceability. That tends to be over the top for some microcontroller applications but, then agin, maybe not. It is like embedded design in general, it depends.
So if you are using what I would call "raw C" then take a look around. There is more than one way to improve your coding standards and you will definitely like have code with fewer bugs.