Usage of a zero-length array (flexible array)

Source: Internet
Author: User

The dnw source code in the previous article uses such a struct:

Struct download_buffer {uint32_t load_addr;/* load address */uint32_t size;/* data size * // size = address (4 bits) + size (4 bits) + Data + verification (2 bits) uint8_t data [0]; // an array of 0 lengths pointing to data/* uint16_t checksum; * // the two following the array are check bits };

Data [0] is a zero-length Array Used for flexible expansion of struct.

Allocate memory space:

buffer = alloc_buffer(file_stat.st_size);

That is:

buffer = malloc(data_size + sizeof(struct download_buffer) + 2);

Data_size is the length of the struct member buffer> data. It is not calculated when the length of the struct is obtained using sizeof (struct download_buffer ).
The length of the data member. In this way, a structure can be dynamically adjusted and allocated to the data member space according to the required space.


Let's take a look at an online example:
Define a struct

typedef struct user_def{    char * name;    int length;    char bytes[0];} user_def_t;

Here we use sizeof (bytes) to find that the result is equal to 0. This bytes is a zero-length flexible array. The usage is as follows:

int alloc_user_def_t(user_def_t * p, int length){    p = (user_def_t)malloc(sizeof(user_def_t) + length);    if (NULL == p)    {        return -1;    }    p->name = NULL;    p->length = length;    memset(p->bytes, 0, length);    return 0;}

In this way, we will write the 0 characters of length into the bytes array, which is equivalent to an Attachment attached to the structure and can be accessed through this array.

Let's look at another online example:


# Include <stdio. h> # include <stdlib. h> # include <string. h> # include <assert. h> struct helloworld_t {int num; char helloworld [0]; // mainly used to obtain the address of an array, which is then accessed by the number of arrays}; int main () {struct helloworld_t * P; unsigned int size = sizeof (struct helloworld_t) + strlen ("Hello world! \ N ") + 1; P = (struct helloworld_t *) malloc (size); Assert (P! = NULL); memcpy (P, "\ x01 \ x00 \ x00 \ x00hello world! \ N ", size); // \ x01 \ x00 \ x00 \ x00 four bytes, which is to assign a value to num // in the memory, the high 8 bits and the low 8 bits reverse... // printf ("% d \ n", p-> num); While (p-> num --) {printf (p-> helloworld );} // printf ("% d \ n", sizeof (helloworld_t); free (void *) P); Return 0 ;}

The output is: Hello world!

In c99, the last element in the structure can be an array of unknown sizes. This is called a flexible array member,
The flexible array member must be at least one other member. Flexible array Members allow the structure to contain an acceptable size
Variable array. The size of the structure returned by sizeof does not include the memory of the flexible array. Structure containing flexible array members
The malloc () function dynamically allocates memory and the allocated memory should be larger than the structure to adapt to flexible arrays.
The expected size.
When defining this struct, the size of the struct has determined the memory size that does not contain the flexible array.
Flexible arrays are compiled by non-staff and do not occupy the structure. It just means that when using a flexible array, you need to treat it as a knot
It is only a member of the constructor. Besides, flexible arrays have nothing to do with struct, but they are just
It is not a formal member of the structure.
It should be noted that c89 does not support such a thing. c99 adds it as a special case to the standard. However, c99
Incomplete type, rather than zero array, is supported in the same way as int item [0]. This form is invalid, and c99 supports
The format is the same as int item []; only some compilers support int item [0]; as non-standard extensions, and in c99
This non-standard extension already exists before release. After c99 is released, some compilers combine the two into one. Of course, the above
Since the memory is allocated using the malloc function, you must use the free function to release the memory:
Free (P );



For example:

typedef struct st_type{int i;int a[0];}type_a;

The GNU Compiler can be compiled. Some compilers report errors and cannot compile (for example, vs series:

typedef struct st_type{int i;int a[];}type_a;

In this way, we can define a variable length struct. Only 4 is obtained by using sizeof (type_a), that is
Sizeof (I) = sizeof (INT ). The array with zero elements does not occupy space. Then we can perform the variable length operation. Connect
The following expression is used to allocate memory to the struct:
Type_a * P = (type_a *) malloc (sizeof (type_a) + 100 * sizeof (INT ));
In this way, we allocate a piece of memory for the struct pointer p. You can use p-> A [n] to easily access variable-length elements (p-> A [0] ~ P-> [99]).
However, at this time, we use sizeof (* P) to test the size of the struct, and found that it is still 4.

So, why not use pointer members in the struct to point to the dynamic memory space of the string?
For example:

struct  ptest{     int  a;     double b;     char  *c;};

Pointer member C points to a string. This method will cause the string to be separated from the struct, and malloc and free will generate fragments for memory management, which is not conducive to operations.
If we connect the string and the struct, the position of the string is followed by the struct, and the code is modified as follows:
Char STR [] = "Hello World ";
Struct Ptest * test = (struct Ptest *) malloc (sizeof (struct Ptest) + strlen (STR) + 1); // + 1 because strlen does not calculate the Terminator
Strcpy (test + 1, STR)

(Char *) (test + 1) is the address of the string "Hello World. C becomes unnecessary and can be removed. However, it is inconvenient to directly use (char *) (test + 1. Therefore, the flexible array can meet the requirements of both the direct reference string and the structure space and the flexible distribution of data domain size.

In this struct, C is a flexible array member. If we regard the dynamic memory allocation pointed to by test as a whole, C is a flexible array with variable length, C has a length of 0 in the struct and does not occupy the space of test. Test-> C is the first address of "Hello World.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.