Share a few practical tips in embedded C
Hi everybody, I'm
杂烩君
. This time I will share with you some practical skills in embedded C.
1. Dynamic binding, callback function
The callback function can achieve the role of dynamic binding and reduce the coupling between layers to a certain extent. Regarding the callback function, I have already written an article before: C language, embedded key knowledge: callback function . Maybe many beginners may not understand the callback function. You can use the following figure to understand:
Generally, the order of function calls is that the upper function (caller) calls the lower function (callee). From the above figure, we can see that function 2 of the lower module calls function 3 of the upper module. This calling process is opposite to the general calling process. This process is called callback, and function 3 of the upper module here is the callback function. The callback function is represented by a function pointer.
The C library stdlib.h contains a sorting function: the qsort function. The prototype of this sorting function is:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*));
parameter:
-
base – Pointer to the first element of the array to be sorted.
-
nitems -- the number of elements in the array pointed to by base.
-
size – The size of each element in the array, in bytes.
-
compar – a function used to compare two elements, that is, a function pointer (callback function).
int compar(const void *p1, const void *p2);
If the compare return value is less than 0 (< 0), then the element pointed to by p1 will be sorted to the left of the element pointed to by p2;
If the return value of compar is equal to 0 (= 0), then the order of the element pointed to by p1 and the element pointed to by p2 is uncertain;
If the compare return value is greater than 0 (> 0), then the element pointed to by p1 will be sorted to the right of the element pointed to by p2.
example:
#include <stdio.h>
#include <stdlib.h>
int compar_int(const void *p1, const void *p2)
{
return (*((int*)p1) - *((int*)p2));
}
void test_qsort(void)
{
int arr[5] = {8, 5, 10, 1, 100};
printf("排序前:");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
qsort((int*)arr, 5, 4, compar_int);
printf("\n排序后:");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
}
int main(void)
{
test_qsort();
return 0;
}
Compilation and running results:
The above is the sharing this time. If there are any errors, please point them out. Thank you. This is the first episode, and we will continue to share more practical programming tips and programming experiences in actual development. Welcome to continue to pay attention. This article only lists some practical tips. It does not mean that they should be used in any scenario. Specific issues need to be analyzed in detail.
2. Use macros to initialize the structure
If you use a structure frequently, it is very convenient to use macros to assign values to the structure.
example:
#include <stdio.h>
#define NEW_RECT(length, width) {(length), (width)}
typedef struct _Rect
{
int length;
int width;
}Rect;
int main(void)
{
Rect rect = NEW_RECT(10, 5);
printf("rect length = %d, width = %d\n", rect.length, rect.width);
return 0;
}
Compilation and running results:
This method is also seen in the underlying gpio driver of RT-Thread:
3. Structure built-in function pointer
We often construct some structures to store data, and then use these structures in some functions. Next time, you might as well tie the data and the functions that operate on the data together to make it clearer.
Related articles: What are incomplete types?
example:
#include <stdio.h>
#define NEW_RECT(length, width) {(calc_area), (length), (width)}
typedef struct _Rect
{
int (*calc_area)(struct _Rect *pThis);
int length;
int width;
}Rect;
int calc_area(struct _Rect *pThis)
{
return (pThis->length * pThis->width);
}
int main(void)
{
Rect rect = NEW_RECT(10, 5);
printf("rect length = %d, width = %d\n", rect.length, rect.width);
printf("rect area = %d\n", rect.calc_area(&rect));
return 0;
}
Compilation and running results:
4. Use do{}while(0) to encapsulate macros
#define DBG_PRINTF(fmt, args...) \
do\
{\
printf("<<File:%s Line:%d Function:%s>> ", __FILE__, __LINE__, __FUNCTION__);\
printf(fmt, ##args);\
}while(0)
For detailed instructions, please refer to previous articles:
Several very practical macro techniques in C language and embedded
5、void*
It has been introduced
before in
the first part of C language object programming: encapsulation and abstraction
void*
.
void*
In fact, we have come into contact with each other on a daily basis, such as:
void *malloc(size_t size) ;
void *memcpy(void *destin, void *source, unsigned n);
......
void *
It is often used to encapsulate functions. Of course, it is also useful in other places, such as defining
void*
a type of private pointer in a structure to facilitate expansion of the structure. When we usually encapsulate our own functions, we can also consider whether it is necessary to use
void*
to make the function more versatile.
end
A mouthful of Linux
Follow and reply [ 1024 ] Massive Linux information will be given away
Collection of wonderful articles
Article recommendation
Click " Read the original text " to view more sharing, welcome to share, collect, like, and watch