Preface:

Char [0] was asked by the interviewer, but didn’t come across the question himself, so he bypassed it.


I have made some replies of my own below this article.

Now I want to explain the char[0] C flexible array problem with my own understanding.

Akik Conscience still lives

Welcome to follow the wechat public account: Yu Linjun

Or add the author’s wechat account: Become_me


Introduction to 0 arrays and flexible arrays

0 array as the name implies, is the length of the array is defined as 0, we generally know array length definition for at least 1 will be assigned to it the actual space, and defines the array of 0 is no space, but if you like the above structure in the last member is defined as a null array, although null array not allocated space, but it can be used as an offset, Because the array name itself represents an immutable address constant. Flexible arrays are also called scalable arrays, and arrays of 0 are flexible arrays.

Because when no introduction of zero-length arrays in the early days, everyone is through the way of fixed length array and pointer to solve, but a fixed-length array defines a large enough buffer, so easy to use, but every time is a waste of space pointer, require the programmer in free space is a must for many free operation, We often return a pointer to the buffer in the function we use, and we can’t guarantee that everyone will understand and comply with our release method, so GNU extends it with a zero-length array. When using data[0], which is a zero-length array, the zero-length array is the name of the array and does not take up storage. This makes memory more efficient.

After C99, a similar extension was added, but in the form of char payload[] (so if you do need the -pedantic parameter when compiling, You can change the type of char payload[0] to char payload[], and this will pass. Of course, your compiler must support C99. If it is too old, it may not support C99.

General use of the 0 array

First we define a structure, and then at the end of a structure, we define an array of length 0, which makes the structure variable length.

As follows:

// 0 length array

struct zero_buffer

{

    int     len;

    char    data[0];

};

Copy the code

In this case, data[0] is just an array name and does not occupy storage space.

The sizeof this structure is the length of its member int by sizeof. Data [0] takes no space. (The array name is just a symbol, it doesn’t take up any space, it just represents an offset in the structure, representing an unmodifiable address constant!)

sizeof(struct zero_buffer) = sizeof(int)

printf("zero struct length is:%d int length is:%d\n",sizeof(struct zero_buffer),sizeof(int));

Copy the code

zero struct length is:4 int length is:4

With this feature, it is easy to construct the data structures we need, such as buffers, packets, and so on.

The structure definition is shown above


Suppose we need to set up a TCP packet to be sent with a length of 15 “Hello My Friend”, so we can define it as follows. Zbuffer ->data indicates the address of the defined data, and len indicates the length of the data.

Open up space for later use

When we use it, we only need to open up the space once.

#define CURR_LENGTH 15

struct zero_buffer  *zbuffer = NULL;



/ / set up

if((zbuffer = (struct zero_buffer *)malloc(sizeof(struct zero_buffer) + sizeof(char) * CURR_LENGTH)) ! = NULL)

{

    zbuffer->len = CURR_LENGTH;

    memcpy(zbuffer->data, "Hello My Friend", CURR_LENGTH);

    printf("%d, %s\n", zbuffer->len, zbuffer->data);

}

Copy the code

Use up free space

Free space can be released once

/ / destroy

free(zbuffer);

zero_buffer = NULL;

Copy the code

Other methods can transmit data of variable length

In addition to arrays of zeros, there is the ability to implement flexible arrays using fixed-length arrays and pointer arrays.

Fixed-length array

A fixed-length array, as the name suggests, is an array with a fixed length inside the structure. The size of the array is set according to the size of the specified data, in order to prevent overflow during storage.

define

// Buffer of fixed length

#define MAX_LENGTH 512

struct max_buffer

{

    int     len;

    char    data[MAX_LENGTH];

};

Copy the code

However, in the process of using, for example, I want to send 512 bytes of data. If I use a fixed-length packet and set the maximum length of the packet MAX_LENGTH to 1024, 512 bytes of space will be wasted and unnecessary traffic will be wasted. Sizeof (struct max_buffer) = sizeof(int)+ sizieof(char) * MAX_LENGTH

Packet construction

Typically, we return a pointer to the buffer data structure max_buffer.

#define CURR_LENGTH 512

struct max_buffer   *mbuffer = NULL;

if((mbuffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) ! = NULL)

{

    mbuffer->len = CURR_LENGTH;

    memcpy(mbuffer->data, "Hello World", CURR_LENGTH);

    printf("%d, %s\n", mbuffer->len, mbuffer->data);

}

Copy the code

The first four bytes are p->len, as the header, which describes the length of the data immediately after the header. Here it is 1024, so the first four bytes are assigned to 1024. We have to specify the length of the packet in a variable, that’s what len does.

The memory immediately following it is the actual data part, and p->data. Finally, a memcpy() copy is made to fill this memory with the data to be sent

Release the space

When you run out of space to release data, just release it

free(mbuffer);

mbuffer = NULL;

Copy the code

In order to avoid buffer overflow, the size of the array is usually set to sufficient space MAX_LENGTH. However, in practice, there is very little data that reaches MAX_LENGTH, so in most cases, most of the buffer space is wasted.

However, the usage process is very simple, the data space is easy to open and release, without the programmer to consider additional operations

Pointer to an array

The difference is that the last element of the zero array defines a data[0], whereas a pointer array is an array of Pointers that need to be defined in the structure. The pointer array does not need to be specific to the last element of the structure.

struct point_buffer

{

    char    *data;

    int     len;

};

Copy the code





Sizeof (point_buffer)= sizeof(int) sizeof(char *) if the structure is decorated with _attribute((Packed)) data alignment, then sizeof(point_buffer)= sizeof(int) sizeof(char *) evaluates to 12 bytes.

Space allocation use

#define CURR_LENGTH 1024

struct point_buffer *pbuffer = NULL;

if((pbuffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) ! = NULL)

{

   pbuffer->len = CURR_LENGTH;

   if((pbuffer->data = (char *)malloc(sizeof(char) * CURR_LENGTH)) ! = NULL)

   {

       memcpy(pbuffer->data, "Hello World", CURR_LENGTH);





       printf("%d, %s\n", pbuffer->len, pbuffer->data);

   }

}

Copy the code

There are two steps to allocate memory

First, you need to allocate a memory space for the structure.

Second, memory is allocated for the member variables in the structure.

The memory allocated in this way is discontinuous and needs to be managed separately. When an array of length is used, it is allocated once, allocating all the required memory at once.

The release of

Conversely, the same thing happens when you release.

free(pbuffer->data);

free(pbuffer);

pbuffer = NULL;

Copy the code

Using the result of a pointer as a buffer only uses one more pointer size, eliminating the need to use a fixed-length array and resulting in no significant space waste.

Struct point_buffer (struct point_buffer, struct point_buffer, struct point_buffer); At this time, we can not assume that users understand the details of our development and release space according to the agreed operation, so it is inconvenient to use, and even cause memory leakage

Summary:

The fixed-length array is easy to use, but it wastes space. The pointer form only uses the space of one more pointer, so it does not waste a lot of space, but it needs to be allocated and released many times. So the optimal solution

The advantages and disadvantages of 0 array and matters needing attention

Advantages: This method is more efficient than declaring a pointer variable in a structure and then allocating it dynamically. Because no indirect access is required when accessing the contents of the array, two fetches are avoided. In addition, arrays of 0 do not waste as much memory as arrays of fixed length.

Disadvantages: In structs, arrays of 0 must be declared at the end, which is limited in usage.

conclusion

This is the zero number group I share, if you have better ideas and needs, you are welcome to add my friend exchange and share ha.

— the END —

Recommended reading

[1] C++ smart pointer do you know?

[2] A brief introduction of software framework for embedded low-level development

[3] How does a program in the CPU run as a must-read

[4] Cartographer environment building and drawing building test

[5] Comparison of simple factory model, factory model and abstract factory model

This public account all original dry goods have been sorted into a catalogue, reply [resources] can be obtained.

Refer to the article: https://blog.csdn.net/gatieme/article/details/64131322