I heard that some people don’t understand flexible arrays?
[Copy link]
1 Introduction
Fixed-length array package
In normal development, when sending and receiving buffer data, if a buffer fixed-length packet is used, assuming the size is 1k, MAX_LENGTH it is 1024. The structure is as follows:
// 定长缓冲区 struct max_buffer { int len; char data[MAX_LENGTH]; };
The size of the data structure >= sizeof(int) + sizeof(char) * MAX_LENGTH In order to prevent data overflow, the length of data is usually set large enough, but this also leads to redundancy of the array. If 512 bytes of data are sent, 512 bytes of space will be wasted. In normal communication, most of them are heartbeat packets, which are much smaller than 1024 bytes in size. In addition to wasting space, it also consumes a lot of traffic. Memory application:
if ((m_buffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL) { m_buffer->len = CUR_LENGTH; memcpy(m_buffer->data, "max_buffer test", CUR_LENGTH); printf("%d, %s\n", m_buffer->len, m_buffer->data); }
Memory release:
free(m_buffer); m_buffer = NULL;
Pointer Packet
In order to avoid wasting space, we can MAX_LENGTH replace the fixed-length array with a pointer, and dynamically allocate CUR_LENGTH space of the same size each time it is used. Data packet structure definition:
struct point_buffer { int len; char *data; };
The data structure size >= sizeof(int) + sizeof(char *) but when allocating memory, two steps are required:
- A piece of memory space needs to be allocated for the structure;
- Allocate memory space for member variables in the structure;
Memory request:
if ((p_buffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL) { p_buffer->len = CUR_LENGTH; if ((p_buffer->data = (char *)malloc(sizeof(char) * CUR_LENGTH)) != NULL) { memcpy(p_buffer->data, "point_buffer test", CUR_LENGTH); printf("%d, %s\n", p_buffer->len, p_buffer->data); } }
Memory release:
free(p_buffer->data); free(p_buffer); p_buffer = NULL;
Although this can save memory, the memory allocated twice is not continuous and needs to be managed separately. The problem is that the memory needs to be applied and released for the structure and data separately. This is undoubtedly a disaster for programmers because it is easy to forget to release memory and cause memory leaks. Is there a better way? That is today's topic, flexible arrays.
2 Flexible Arrays
What is a flexible array?
Flexible array members are also called scalable array members. This code structure arises from the need for dynamic structures. In daily programming, sometimes you need to store a string with a dynamic length in a structure. In view of the important role played by this code structure, C99 even included it in the standard:
As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
Flexible arrays are a feature introduced by the C99 standard, so when your compiler prompts unsupported syntax, please check whether you have enabled the C99 option or higher version support. The definition of the C99 standard is as follows:
struct test { short len; // 必须至少有一个其它成员 char arr[]; // 柔性数组必须是结构体最后一个成员(也可是其它类型,如:int、double、...) };
- Flexible array members must be defined in the structure and must be the last element;
- A structure cannot have only flexible array members;
- Flexible arrays do not occupy memory.
At the end of a structure, declaring an empty array can make the structure variable-length.
For the compiler, the array with a length of 0 does not take up space at this time, because the array name itself does not take up space, it is just an offset. The symbol of the array name itself represents an unmodifiable address constant, but for the size of this array, we can dynamically allocate it. For the compiler, the array name is just a symbol, it does not take up any space. In the structure, it only represents an offset, representing an unmodifiable address constant!
With this feature of flexible arrays, it is easy to construct structures, such as buffers, data packets, etc. In fact, flexible array members have their special usage when implementing skip lists. Flexible array members are also used in the SDS data structure of Redis and in the implementation of skip lists. Its main purpose is to meet the need for variable-length structures and to solve the memory redundancy and array out-of-bounds problems when using arrays.
Flexible array solution introduction example
//柔性数组 struct soft_buffer { int len; char data[0]; };
Data structure size = sizeof(struct soft_buffer) = sizeof(int) , such variable-length arrays are often used to construct variable-length data packets in network communications, which will not waste space or network traffic. Apply for memory:
if ((softbuffer = (struct soft_buffer *)malloc(sizeof(struct soft_buffer) + sizeof(char) * CUR_LENGTH)) != NULL) { softbuffer->len = CUR_LENGTH; memcpy(softbuffer->data, "softbuffer test", CUR_LENGTH); printf("%d, %s\n", softbuffer->len, softbuffer->data); }
Freeing memory:
free(softbuffer); softbuffer = NULL;
Comparing the use of pointers and flexible arrays, we can find the advantages of using flexible arrays:
- Since the pointer addresses used in the structure are discontinuous (malloc twice), while the flexible array addresses are continuous, only one malloc is required. Similarly, releasing the former requires two times, while the latter can be released together.
- When copying data, when a structure uses a pointer, the memory it points to must be copied. Discontinuous memory will cause problems. Flexible arrays can be copied directly.
- Reduce memory fragmentation. Since the addresses of the flexible array and structure members of the structure are continuous, they can apply for memory together, thus avoiding memory fragmentation to a greater extent. In addition, since the member itself does not occupy the structure space, overall, it occupies slightly less space than ordinary array members.
Disadvantages: There are requirements for the structure format, it must be placed at the end and is not the only member.
3 Conclusion
In daily programming, sometimes you need to store a string (or other data types) of dynamic length in a structure. You can use flexible arrays, which is a method that can cleverly solve the redundancy of array memory and the problem of array out-of-bounds. It is worth learning and reference.
Book a trial course on embedded systems, Internet of Things, Java big data, Python artificial intelligence, and hardware PCB, add xydgz118
|