What are the real benefits of a flexible array element?

After reading some messages related to the element of the flexible array , I still do not quite understand why such a function is needed.

Possible duplicate:
Flexible array members in C - bad?
Is this an element of the flexible array structure in C?

(Kill me if I did not solve my problem from possible recurring questions above)

What is the real difference between the following two implementations:

struct h1 { size_t len; unsigned char *data; }; struct h2 { size_t len; unsigned char data[]; }; 

I know that the size of h2 is as if the element of the flexible array (data) were omitted, i.e. sizeof(h2) == sizeof(size_t) . And I also know that the flexible element of the array can only be displayed as the last element of the structure, so the initial implementation may be more flexible in the data position.

My real problem is why does the C99 add this feature? Just because sizeof (h2) does not contain real data size? I am sure that I should skip some more important points for this function. Please indicate this to me.

+6
source share
3 answers

The two structures in your message do not have the same structure at all. h1 has an integer and a pointer to char. h2 has an integer and an inline character array (the number of elements determined at run time may not).

In other words, in h2 character data is inside the structure. In h1 it must be somewhere outside.

This is of great importance. For example, if you use h1 , you need to take care of allocating / releasing the payload (in addition to the structure itself). With h2 only one distribution is required / free, everything is packed together.

One case where using h2 might make sense is that you are communicating with what is expecting a message in the form of {length,data} pairs. You assign an instance of h2 , asking for sizeof(h2)+how many payload chars you want , populate it, and then you can pass it all in one write (taking care of the entiance and, of course, that). If you used h1 , you will need two calls to write (if you do not want to send the address of the data memory, which usually does not make sense).

So, this function exists because it is convenient. And the various (sometimes not portable) tricks that were used before to imitate this feature. Adding it to the standard makes sense.

+7
source

The main reason the Committee introduced flexible array members was to implement the famous struct hack . See the quote below from the C99 Justification, especially the part that I am adding.

Justification for an International Standard - Programming Languages ​​- C §6.7.2.1 Structure and Association Specifications

There is a common idiom known as “struct hack” for creating a structure containing a variable-sized array:

 struct s { int n_items; /* possibly other fields */ int items[1]; }; struct s *p; size_t n, i; /* code that sets n omitted */ p = malloc(sizeof(struct s) + (n - 1) * sizeof(int)); /* code to check for failure omitted */ p->n_items = n; /* example usage */ for (i = 0; i < p->n_items; i++) p->items[i] = i; 

The validity of this design has always been questionable. In response to a single Report defect, the Committee decided that it was undefined because the p->items array contains only one element, regardless of whether space exists. An alternative design was proposed: the size of the array is larger than the largest possible case (for example, using int items[INT_MAX]; ), but this approach is also undefined for other reasons.

The committee considered that while it was not possible to implement “structural hacking” in C89, it was nevertheless a useful tool. Therefore, a new function of "members of a flexible array" was introduced. Besides the empty brackets and the removal of "-1" in the malloc call, this is used in the same way as struct hack, but now the code is clearly valid.

There are several limitations to flexible array elements that ensure that using code with them makes sense. For example, there must be at least one other member, and the flexible array must happen last. Similarly, structures containing flexible arrays cannot be found in other structures or arrays. Finally, sizeof , applied to the structure, ignores the array, but considers that there will be padding before it. This makes calling malloc as simple as possible.

+3
source

I do not know if this is considered an important point, but GCC docs points to this:

GCC allows you to statically initialize elements of a flexible array. This is equivalent to defining a new structure containing the original structure, followed by an array of sufficient size to hold the data. For instance. subsequently, f1 is constructed as if it were declared as f2.

 struct f1 { int x; int y[]; } f1 = { 1, { 2, 3, 4 } }; struct f2 { struct f1 f1; int data[3]; } f2 = { { 1 }, { 2, 3, 4 } }; 

(taken from http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html )

+1
source

Source: https://habr.com/ru/post/959112/


All Articles