Structures and classes in C++ - Embedded.com

Structures and classes in C++

C++ continues to be a minority language for embedded development but is commonly adopted by developers when projects become too large for C to be used efficiently. These developers are typically transitioning from C to C++ and the subtle differences between the languages represents a significant part of their learning curve. C++ has structures, like C does, by they are not the same. C++ has classes, which are remarkably similar to structures. This article unpicks the details of these language elements.

Structures in C

A structure in C is a customized, composite data item (object), that may be constructed from the existing built-in data types (int, char, etc.), bit fields (integers of specified bit size) and other structures. The idea is to aggregate a number of items of data that belong together. For example, a structure to hold 3-dimensional coordinates might look like this:

struct coordinates
{
   float x;
   float y;
   float z;
};

This code tells the compiler what a struct coordinates looks like. You can then go on to declare variables of this type thus:

struct coordinates location;

The variable location is of type struct coordinates and its internal fields may be addressed using the “dot” operator:

location.x = 1.0;
location.y = 2.0;
location.z = 9.99;

Of course, a similar effect could be achieved using three separate float variables with names like location_x etc. However, it is much easier to handle location as a single variable that can be passed to functions etc.

The ability to include bit fields gives structures a capability not available elsewhere in C. Here is an example:

struct bitreg
{
   unsigned up: 3;
   unsigned down: 3;
   unsigned polarity: 2;
};

Each of the fields in a variable of type struct bitreg has a specific bit size. The complier ensures that the data is stored in a sensible way, so we would expect such a variable to fit into one byte. Furthermore, all the “bit bashing” code to access the fields within the byte is generated automatically. So, the programmer can simply access them thus:

struct bitreg control;
 
control.up = 1;
control.down = 2;
control.polarity = 3;

For the most part, using structures in C is quite straightforward and makes the code easier to understand with no impact on execution efficiency. However, there are two points of which embedded developers should be aware:

  • Modern, high-end (typically 32-bit) processors have instruction sets that readily accommodate the use of structures. Indeed, they were designed to do just this. However, most lower-end CPUs do not offer such efficiencies, so the use of structures needs care.
  • Bit fields are a nice feature and can result in efficient and readable code. Embedded developers may immediately spot an opportunity: use bit fields to access device control registers. Many peripheral devices have registers that are 1-word or 1-byte wide that contain various bit fields. This looks like a great match and sometimes it can be made to work. But there are two issues:
    • The exact layout of the bit fields is determined by the compiler. If everything maps correctly onto a device, the code may work fine. However, a change of compiler, or even just a compiler update, might break the code.
    • The code generated by the compiler to access the bit fields will most likely use a number of AND/OR operations and multiple accesses to the register, which may be problematic. Furthermore, some device registers are write-only and that would never be accommodated in compiler generated code.

Although a C structure looks somewhat like a new data type, it is not really. A data type would normally have a range of operations that can be performed on it; this is not the case for a C structure. To do anything to a C structure, other than making a pointer to it, you need to access the internal fields. This matter is addressed in C++.

Classes in C++

The C++ language has a number of object-oriented capabilities. One of these is the concept of a class, which enables the description of something much more like a new data type. A variable (normally called an object) may be instantiated from the class; i.e. it is an object of this new type.

A C++ class has almost exactly the same syntax as a C structure and some very similar capabilities. However, there are some important differences:

  • A class can also contain functions (called methods).
  • The member variables and methods are hidden from the outside world, unless their declaration follows a public:
  • There can be a pair of special methods – the constructor and destructor – that are run automatically when an instance of the class (an object) is created and destroyed respectively.
  • Operators to work on the new data type can be defined using special methods (member functions).
  • One class can be used as the basis for the definition of another (this is termed inheritance).
  • Declaring a variable of the new type (an instance of the class; an object) requires just the name of the class – the keyword class is not required.

Most of these features are illustrated in this example:

class myclass
{
   char  a;
   int   b;
public:
   void fun();
   myclass();
   ~myclass();
};
 
myclass myobj;
 
myobj.fun();

The member variables a and b are only accessible to the three member functions fun(), myclass() and ~myclass(). The latter two functions are the constructor and destructor. Only fun() is likely to be called by user code. The actual code for all three functions would be defined elsewhere are associated with the class using the :: operator, thus:

void myclass::fun()
{
  ...

Structures in C++

In addition to classes, C++ has structures, which are backwards compatible with C. However, a C++ structure also has the same additional capabilities that are possessed by classes. The is just one single difference between a structure and a class in C++. The default accessibility of member variable and functions in a class is private, as we have seen; the default in a struct is public. Thus, the functionality of the earlier class could also be expressed like this:

struct mystruct
{
   void fun();
   myclass();
   ~myclass();
private:
   char  a;
   int   b;
};

Using classes and structures in C++

Having acquired this information, you are urged not to exploit it too heavily. There are many reasons for only using structures for the kind of functionality they offered in C and classes when you need the extra capabilities. Primarily, it is an issue of code readability. Another developer may not be so clear on the details and code written in a “non-standard” way will be confusing.

A key priority when you are writing code is to ensure that it is readable (=maintainable). Somebody – it could be you – might need to look at this code in a year’s time and understand what it does. Some advice: Assume that the person who will maintain your code is an armed psychopath, who has limited patience, and knows your home address.


Colin Walls has over forty years’ experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, Colin is an embedded software technologist with Mentor, a Siemens business, and is based in the UK. His regular blog is located at: https://blogs.sw.siemens.com/embedded-software/. He may be reached by email at colin_walls@mentor.com.

 

2 thoughts on “Structures and classes in C++

  1. C++ will continue to struggle in microcontrollers as long as the companies that make the microcontroller uses C. AtMEL(micro chip) probably one of the largest
    Manufactures, has their own IDE and uses C exclusively.
    I have written some libraries in C++ but could of just as easily written them in C.

    Log in to Reply

Leave a Reply

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