How to write easy-to-maintain embedded code?

Follow + star official account , don't miss exciting content

bcf4c4070801d43da43ba3ebc1b1bd9e.gif

Transfer from | Embedded hodgepodge

In the past, due to limited memory resources, memory usage and code size were considered comprehensively when writing code.

Today, chip resources are no longer as scarce as before. If you want the code to be easier to maintain, you have to sacrifice the amount of code.

object-oriented C

The object-oriented language is closer to the human way of thinking, and greatly reduces the complexity of the code, while improving the readability and maintainability of the code. The traditional C code can also be designed to be more readable and easy Maintained, beautiful code with less complexity, this article will illustrate this with a practical example.

basic knowledge

structure

In addition to providing basic data types, C language also provides users with the ability to customize data types, that is, structures. In C language, you can use structures to represent any entity. The structure is the embryonic form of the concept of the class in the object-oriented language, such as:

typedef struct{ 
    float x; 
    float y; 
 }Point;

A point in a plane coordinate system is defined, and there are two domains in the point, x coordinate and y coordinate.

Fields in a structure are called members of the structure. The data types in the structure can be simple data types, or other structures, and even the structure itself can be nested. For example, a standard linked list structure can be defined as follows:

typedef struct node{ 
    void *data;// 数据指针
    int dataLength;// 数据长度
    struct node *next;// 指向下一个节点
 }Node;

It can be seen that the type of the next pointer in the structure node is the node type.

function pointer

Pointer is the soul of C language, and it is where C is more flexible and powerful than other languages. So learning C language must have a good grasp of pointers. A function pointer is a pointer pointing to the first address of a function in the memory map. Through a function pointer, a function can be passed as a parameter to another function and called at an appropriate time, thereby realizing functions such as asynchronous communication.

For example, the prototype of the signal registration function in UNIX/Linux system is as follows:

void (*signal(int signo,void (*func)(int))) (int)

When using it, you need to define a signal handler (signal handler) externally, and then use signal(sigNo, handler) to register the handler on the process. When the signal occurs, the process can call back the signal handler.

Using function pointers as members of structures

As mentioned earlier, the members of the structure can be simple data structures, or other structures, and of course, they can also be pointers. When the function pointer is used as a member of the structure, and these functions are only used to operate the data in the structure, an independent entity can be formed, which contains both data and operations on the data, so naturally Leads to the concept of class (class).

Features of object-oriented languages

Generally speaking, inheritance, encapsulation and polymorphism are considered as the three features that object-oriented languages ​​must support, and it is through these three features that object-oriented is better than process-oriented.

Due to the language developer's propaganda or other reasons, the object-oriented idea on the surface should be realized through the language as the carrier. However, in fact, object-oriented is a kind of software design idea, which can be completely independent of the specific implementation. of.

Even so, it is undeniable that these so-called pure object-oriented languages ​​are much better than process-oriented languages ​​in terms of code readability and matching with people's natural thinking.

Object Orientation at Language Level

We generally want to describe an object, and generally need to describe some properties of this object. For example, a box (box) is an entity, which has 6 faces, has properties such as color, weight, and whether it is empty, and can put things in it. something comes out.

In object-oriented languages, such an object is usually abstracted into a class (class):

class Box{ 
    clolr color; 
    int weight; 
    boolean empty; 
    
    put(something); 
    something get(); 
 }

When operating on the box, you can do the following actions:

Box.put(cake); 
 Box.get();// 取到某个东西,从盒子中。

In process-oriented languages, entities are usually passed to a function that runs through the whole world. Taking Box as an example, when operating on Box, it is often like this:

Put(Box, cake);// 将一个蛋糕放到盒子中
 Get(Box);// 从盒子中取出某个东西来

Obviously, the first code form is more in line with common sense, so most object-oriented languages ​​provide support for details at the language level, which greatly increases the readability and comprehensibility of the code.

C language, as a flexible and simple language, we can realize such a more beautiful code form through the simple mechanism provided by C.

Object Orientation in C

As mentioned earlier, object-oriented is a software design idea, which is language-independent. In this section, I give an example of a linked list (list) to illustrate how to design an object-oriented code in C language.

define interface

Interface is a relatively important concept in object-oriented language. The interface only tells what functions the entity that implements the interface can perform, but does not expose the way of implementation. The advantage of this is that the implementer can adjust the implementation without touching the code of the interface user.

Let's take a look at the interface definition of the linked list:

Listing 1. Interface definition for linked list

#ifndef _ILIST_H 
 #define   _ILIST_H 
 
 // 定义链表中的节点结构
 typedef struct node{ 
    void *data; 
    struct node *next; 
 }Node; 
 
 // 定义链表结构
 typedef struct list{ 
    struct list *_this; 
    Node *head; 
    int size; 
    void (*insert)(void *node);// 函数指针
    void (*drop)(void *node); 
    void (*clear)(); 
    int (*getSize)(); 
    void* (*get)(int index); 
    void (*print)(); 
 }List; 
 
 void insert(void *node); 
 void drop(void *node); 
 void clear(); 
 int getSize(); 
 void* get(int index); 
 void print(); 
 
 #endif   /* _ILIST_H */

In the IList interface, it can be clearly seen that for a list entity (that is, an object), operations such as insert, drop, clear, getSize, get(index) and print can be performed on it.

Implementation of the interface

Listing 2. The constructor

Node *node = NULL; 
 List *list = NULL; 
 
 void insert(void *node); 
 void drop(void *node); 
 void clear(); 
 int getSize(); 
 void print(); 
 void* get(int index); 
 
 List *ListConstruction(){ 
    list = (List*)malloc(sizeof(List)); 
    node = (Node*)malloc(sizeof(Node)); 
    list->head = node; 
    list->insert = insert;// 将 insert 函数实现注册在 list 实体上
    list->drop = drop; 
    list->clear = clear; 
    list->size = 0; 
    list->getSize = getSize; 
    list->get = get; 
    list->print = print; 
    list->_this = list;// 用 _this 指针将 list 本身保存起来
 
    return (List*)list; 
 }

It should be noted that the _this pointer here, the _this pointer can ensure that the external operation on the list is mapped to the operation on _this, thus simplifying the code. Listing 3. Insertion and deletion

// 将一个 node 插入到一个 list 对象上
 void insert(void *node){ 
    Node *current = (Node*)malloc(sizeof(Node)); 
    
    current->data = node; 
    current->next = list->_this->head->next; 
    list->_this->head->next = current; 
    (list->_this->size)++; 
 } 
 
 // 删除一个指定的节点 node 
 void drop(void *node){ 
    Node *t = list->_this->head; 
    Node *d = NULL; 
    int i = 0; 
    for(i;i < list->_this->size;i++){ 
        d = list->_this->head->next; 
        if(d->data == ((Node*)node)->data){ 
            list->_this->head->next = d->next; 
            free(d); 
            (list->_this->size)--; 
            break; 
        }else{ 
            list->_this->head = list->_this->head->next; 
        } 
    } 
    list->_this->head = t; 
 }

For other implementation codes, please refer to the download section. Due to space limitations, it is no longer meaningful to list them here.

test

test code

Well, all the work done above is to ensure that our API exposed to users can be as concise and beautiful as possible. Now it's time to test: List 4. Test code

int main(int argc, char** argv) { 
    List *list = (List*)ListConstruction();// 构造一个新的链表
    
 // 插入一些值做测试
    list->insert("Apple"); 
    list->insert("Borland"); 
    list->insert("Cisco"); 
    list->insert("Dell"); 
    list->insert("Electrolux"); 
    list->insert("FireFox"); 
    list->insert("Google"); 
    
    list->print();// 打印整个列表
            
    printf("list size = %d\n",list->getSize()); 
    
    Node node; 
    node.data = "Electrolux"; 
    node.next = NULL;  
    list->drop(&node);// 删除一个节点
    
    node.data = "Cisco"; 
    node.next = NULL; 
    list->drop(&node);// 删除另一个节点
    
    list->print();// 再次打印
    printf("list size = %d\n",list->getSize()); 
    list->clear();// 清空列表
 
    return 0; 
 }

Figure 1. Running results

9558b23a59fcdd4045eb085c1418b813.png

conclusion

The UNIX platform born of the C language advocates such a design philosophy: make the design as simple as possible, allowing users to connect these simple tools into powerful and complete applications like building blocks.

It should be said that C better inherits this point. The C language is very concise and powerful. However, since the C language was born relatively early, the object-oriented thinking was still immature at that time, so a large number of procedural C applications appeared. So as to give people an illusion that C language is a process-oriented language. In fact, C only provides some simple, powerful and general-purpose capabilities. As for what kind of building blocks you want to build, it is all up to you.

Disclaimer: The material of this article comes from the Internet, and the copyright belongs to the original author. If it involves copyright issues, please contact me to delete.

------------ END ------------

9fa7fc7b50807b7ea99998c423818af7.gif

●Column "Embedded Tools "

●Column "Embedded Development"

●Column "Keil Tutorial"

●Selected tutorials in the embedded column

Pay attention to the official account and reply " Jiagroup " to join the technical exchange group according to the rules, and reply " 1024 " to view more content.

fedfa6bcb8d2d49f08e8c110e1e5a34d.jpeg

5bb34571fff4b7836da20e8e7d283729.png

Click " Read the original text " to see more sharing.

Guess you like

Origin blog.csdn.net/ybhuangfugui/article/details/132463382