Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

I am Lao Wen, an embedded engineer who loves learning.Follow me to become even better together!

I remember when I first started working, a master told me that if you are not familiar with longjmp and setjmp, you should not call yourself a C language expert. At that time, I was half-convinced, but to move towards the direction of expertise, I spent some time learning how to use longjmp and setjmp.

Later, I realized that it is not just about jumping around; it is a sophisticated exception handling mechanism that can indeed be very useful in certain situations.

To showcase my skills, I also used it a few times in my programs. Gradually, I discovered that the benefits of such techniques come at a cost, disrupting the structured design of the program, making it difficult to read, especially for beginners.

Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

Finally, I understood that this technique is merely a seasoning; using it a few times in rare situations can simplify problem handling. If you use seasoning as a staple, you will definitely lose sight of the main goal, and the program will appear malnourished.

In fact, being familiar with longjmp and setjmp does not determine whether you are a C language expert; it is not a causal relationship. However, if I could apply that master’s words, I would say that if you are not familiar with function pointers, you should not call yourself a C language expert. Why do I say this? Is function pointers that complicated?

Of course not. Anyone with a bit of programming knowledge, regardless of whether they understand C language, can grasp the concept of function pointers in C within ten minutes.

The reason is that the difficulty does not lie in the concept and syntax of function pointers themselves, but in when and where to use them. Function pointers are not just a syntactical issue; more importantly, they are a design category.

A true expert should not only understand the syntactical techniques but also the design methods. Can one be considered an expert without understanding design? Do you doubt that I am exaggerating?

Let’s first look at how function pointers relate to design methods:

Related to Layered Design

Layered design is no longer a new concept; the benefits of layering are well-known, with the most obvious being the simplification of complexity and isolation of changes. By adopting layered design, each layer only needs to care about its own concerns, which reduces system complexity. The interaction between layers is limited to a narrow interface; as long as the interface remains unchanged, changes in one layer will not affect others, thus isolating changes.

The general principle of layering is that the upper layer can directly call functions of the lower layer, while the lower layer cannot directly call functions of the upper layer. This sounds simple, but in reality, the lower layer often needs to call functions of the upper layer. For example, when copying a file, a function to copy files is called from the interface layer.

The interface layer is the upper layer, and the file copy function is the lower layer, so it is natural for the upper layer to call the lower layer. However, if you want to update a progress bar while copying the file, problems arise.

On one hand, only the file copy function knows the progress of the copy, but it cannot update the interface’s progress bar. On the other hand, the interface knows how to update the progress bar, but it does not know the progress of the copy.

What to do? A common approach is for the interface to set a callback function for the file copy function, which calls this callback function at appropriate times to notify the interface to update the status.

Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

Related to Abstraction

Abstraction is one of the most important concepts in object-oriented programming and is where the power of object-oriented programming lies. Object-oriented programming is just a way of thinking; everyone knows that it is possible to implement object-oriented programming using C language. This is not just to follow trends, but a practical method. If you doubt this, you can look at open-source codes like GTK+ and the Linux kernel.

Interfaces are the highest level of abstraction. In the Linux kernel, the concept of interfaces is ubiquitous, such as the Virtual File System (VFS), which defines an interface for file systems. As long as you follow the specifications of this interface, you can develop your own file system.

Device drivers are even more so; different device drivers have their own set of interface specifications. When developing your own device drivers, you only need to follow the corresponding interface specifications. How are interfaces represented in C language? It is simple: a set of function pointers.

Related to Separating Interface from Implementation

Programming against interfaces rather than implementations is the first design principle of “Design Patterns.” The goal of separating interfaces from implementations is to isolate changes. Software is subject to change; if we cannot isolate the changing elements, it leads to a situation where a single change can affect the entire system, which is something everyone wants to avoid.

Since C language can implement object-oriented programming, it can naturally utilize design patterns to separate interfaces from implementations. Patterns like Bridge, Strategy, State, Proxy, etc., all require the use of function pointers in C language.

Related to the Principle of Loose Coupling. Compared to object-oriented programming, procedural programming appears weak because it cannot intuitively map real-world models to computers.

Procedural programming emphasizes layered control, while object-oriented programming emphasizes collaboration between objects. In the real world, objects are rarely in hierarchical relationships; they are mostly in peer relationships. This means that interactions between objects are often bidirectional, which increases the coupling between objects.

Coupling itself is not wrong; in fact, coupling is essential. Without coupling, there is no collaboration, and objects cannot form a whole, making it impossible to accomplish anything. The key is that coupling should be appropriate; under the premise of achieving the desired functionality, coupling should be as loose as possible. This way, changes in one part of the system will have minimal impact on other parts.

Function pointers are the best tool for decoupling object relationships. The Signal mechanism (such as boost’s signal and glib’s signal) is a typical example. An object’s state may change (or trigger some events), while other objects care about its changes. Once a change occurs in that object, other objects need to perform corresponding operations.

If that object directly calls functions of other objects, the functionality is achieved, but the coupling between objects is too tight. How can we minimize this coupling? The signal mechanism is a good solution.

Its principle is roughly as follows: other objects that care about the changes of that object actively register a callback function with that object. Once a change occurs in that object, it calls these callback functions to notify other objects. The functionality is still achieved, but the coupling between them is reduced.

In C language, solving these problems without using function pointers would be very difficult. In programming, if you have never thought of using function pointers, it is hard to imagine that you are a C language expert.

Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

https://blog.csdn.net/absurd/article/details/6474063

-END-

Previous Recommendations: Click the image to readEmbedded Software Design: A Colleague Claims to be a C Language Programming Expert

Is it necessary to establish a hardware abstraction layer in embedded software architecture design?

Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

In embedded C language, program variable initialization has so many nuances!

Embedded Software Design: A Colleague Claims to be a C Language Programming Expert

For embedded programmers, how difficult and complex is it to switch to hardware?

I am Lao Wen, an embedded engineer who loves learning.Follow me to become even better together!

Leave a Comment