Object-oriented C is simple

Although most C programmers aren't proficient in C++, they can still use simple object-oriented practices. Here's part one in a series of blogs presenting simple ways to mimic object-oriented practices in C.

I'm a strong proponent of using C++ to write embedded systems firmware. The facilities C++ brings to bear enables developers to create highly-portable object-oriented code. One of the great benefits of C++ is that it enforces rules that require the writer to navigate in object-oriented channels of thought and action. Without the use of object-oriented (OO) practices, over time you will lose clear lines of independent behavior. The result will be hidden interdependencies of subsystems that should only be known to one another through defined public interfaces.

So what about C? You can use C in ways that mimic C++'s principles and to some degree enforce OO constructs. In C, you don't have the protection of the compiler. To use OO practices in C, therefore, you need to create a set of rules and play by them. Choose your rules carefully–the rules you follow can make your job harder or easier, especially when debugging. Unlike some rules that require a bit of detective work, a violation of the rules I present here will be as clear as day to spot even for the casual observer of the source.

It's elementary
The concept of using OO practices in C is one of my favorite topics. Techniques for adapting OO to C can be simple to learn and elegant to implement. With this blog, I'll start exploring some of the simple ways we can achieve OO practices in C.

Tip: Keep it simple. How often do you look at code that has solved a complex challenge and say to yourself, “Wow, how simple.” If you can master the art of taking a complex problem and creating a simple, elegant solution, you'll be revered by every firmware engineer who will ever have to support or use your code. To me, simple should always be the goal. Always.

So let's consider the concept of public and private attributes and methods. In C++ you get encapsulation and abstraction with compiler enforcement. What prevents us from having this in C? Well, the C compiler has no concept of encapsulation and abstraction, so we have to adhere to some simple rules to get the same results. Here are the first two rules:

Rule #1: Place public declarations of functions and variables in a separate file from those that are private to the module.

Rule #2: Only allow the use of headers from public declarations in the #include directive.

Let me elaborate with an example.

Say your product contains one motion sensor (we'll cover multiple instances in a later blog). What might we want to keep private about the sensor so as to maintain strong abstraction? Answer: the specific specifications of the sensor. What might we want to be public? Answer: motion detection. Did we detect motion or not?

So how do we easily enforce separation? Rule #1 and #2 and…

Rule #3: Embed in the file names whether the content is public or private.

One simple way to enforce Rules 1 and 2 is to embed in the name of your files whether they are private or public. Immediately, it becomes loud and clear if you're violating Rule 2 whenever you look at your list of file includes.

Public Source File:  MotionSensorPublic.cPublic Header File:  MotionSensorPUBLIC.hPrivate Source File: MotionSensorPrivate.c Private Header File: MotionSensorPRIVATE.h 

This is just one method. I've also used other naming conventions as well as just separating the headers while leaving the functions in one file. All that matters is that you follow these simple rules. As a result, a violation of Rule 2 will stand out like a thorn on a rose bush if you include a private header:

//// File Name:         FilenamePrivate.c// File Description:  Some description of the file's contents.// Author:            Who to blame.//#include "PwmPUBLIC.h"#include "SpiPUBLIC.h"#include "LedPUBLIC.h"#include "SensorPRIVATE.h"#include "WatchdogPUBLIC.h"

So tell me you can't find the rule violation? Clearly one of these things is not like the other.

Next time
I've touched on a simple and easily enforceable setof rules that can be applied to your firmware's file-naming convention with the goal of creating object-oriented C. Notice the simplicity of it. That's always got to be the goal. These rules are like E =MC 2 — simple and simply enforceable. Much more to come on this fascinating topic so stay tuned and I'll see you in the trenches.

Robert Scaccia is a firmware consultant and president of USAFirmware, LLC. He is very active with a large network of firmwareconsultants throughout the United States and Canada, is chair of theIEEE Cleveland Computer Society, and founded the largest regional, as well as international, firmware group on LinkedIn. Email him at , or visit or

21 thoughts on “Object-oriented C is simple

  1. Good topic. I've done object oriented development in C myself, and I'm looking forward to seeing the direction Robert is going to take here.

    @Studleylee, I also noticed the apparent inconsistency in file naming. I say apparent because I'm waiting to see i

    Log in to Reply
  2. Apart the lack of a C++ compiler for your architecture (8-bit processors only?), the use of Object Oriented C does not seem a good idea for me. Why reinvent the wheel?

    I used OOC twenty years ago only for this reason, and switched to C++ as soon as a dece

    Log in to Reply
  3. @JChMethae, many small processors do not support C++ compilers and the decision to move to C++ is not in the hands of the guys in the trenches. Young engineers (and older) need some guidance and if the organization isn't ready to move to C++ then the next

    Log in to Reply
  4. @KarlS thanks for the comments.

    Yes rule 2 is for only public headers. I put #include “sensorPRIVATE.h” as an example of a violation of that rule. Now there is an important exception. Let's use my MotionSensorPublic module. We will need in MotionSensorPu

    Log in to Reply
  5. C++ emulation under C is inferior to using C++ directly.
    Even 8 bit processors such as Atmel AVR can be programmed in C++ (Arduino is based on the AVR and is written completely in C++). So, why no use the Real Thing?

    Log in to Reply
  6. C++ is the best solution; I agree completely!

    The issue here isn't whether or not C++ should be used. The issue is whether or not the guys in the trenches doing the work are given the opportunity to learn and use C++ on their projects.

    If they are not,

    Log in to Reply
  7. Thanks. I develop mostly in C++ (on ST STM32 and Energy Micro EFM32) for all the OO reasons you cite. I hope your article contributes to using OO principles more in embedded software development.

    Log in to Reply
  8. RogerC and Studleylee, thanks for noticing the filename capitalization inconsistencies. We've corrected them in the article above.

    –Susan Rambo
    Managing editor

    Log in to Reply
  9. That's the goal. If engineers that are not developing using C++ think and design using OOC principles, it should make for an easier transition with more enthusiasm and less fear.

    Log in to Reply
  10. I have been developed an embedded system with C++ on ARM7 processor, and finally we figured out its performance is not acceptable, and then moved back to C.
    I have developed a way to do OOC, which also includes how to inherite from other structures, and ho

    Log in to Reply
  11. There are features of C++ that will effect performance and should be avoided in embedded applications. Examples; RTTI, stl, streams. You also need to be aware of the impact of copy constructors and dynamic memory allocation. But for the majority of C++

    Log in to Reply
  12. @Steve.W, thanks for your comments. C++ performance impact is an area of Dan Saks expertise so I would recommend you seek his council on this topic. He has some very interesting perspectives on this.

    I would tend to agree with you that trying to replace

    Log in to Reply
  13. Having written ooc I can say the performance between a proper v-table in c and c++ is identical. I remember the c implementation was 50% the size of the c++ one although I can't remember if I had used any std features or not. I thinking when one just use

    Log in to Reply
  14. Plus, learning to do a bit of OOC might help newer Engineers understand a bit of what's happening “under the hood” with their C++ compiler. A bit like doing some ASM helps with understanding what the C compiler/code is doing…

    Log in to Reply
  15. Embedded SOM on an 8 bit 8051:

    ExternTimer(ledOffTimer);
    ExternTimer(ledFlashTimer);
    static void printStuff(word arg)
    {
    // a place to print stuff
    print(“n”);
    print(“interval =%un”, ledFlashInterval);
    print(“duration =%un”, ledFlashDuration);

    ob

    Log in to Reply
  16. Why do we need SensorPRIVATE.h you can simply declare private data in Sensor.c just like that:

    Sensor.h

    typedef struct Sensor {
    int p; //(public member)
    } Sensor;

    Sensor.c
    #include “Sensor.h”

    typedef struct SensorPrivate {
    Sensor sensor;
    int pr;

    Log in to Reply
  17. In C one can decide to store the vtable inside object (optimizes cpu) or store vtable separate (optimizes memory)

    C++ always stores only pointer to vtable inside object

    Log in to Reply
  18. I am 100% agree C++ is better to use.
    The only thing one may need C is to interface with other languages like Objective-C.

    PS: Last week I developed so called IosSocket C interface for Objective-C developer can provide me Network Connectivity from iOS app

    Log in to Reply
  19. “Having programmed many years in both C and C++ and currently working in C for embedded systems, I have implemented a lot of what is being shown here. The exception for me is that I don't create an include file for the private functions as I declare them d

    Log in to Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.