In fact, very early in the look at Linux to see this thing, and later in the Li Xianjing "System programmer growth Plan" saw a similar definition, so in mind to summarize, the results found that the online has been a good summary of cattle, and then turned over, thank you for sharing, this is my driving force!
At the same time, it needs attention: ISO/IEC 9899-1999, it is illegal to write this, this is only the extension of GNU C, GCC can allow the existence of this grammatical phenomenon. (C99 allowed.) Microsoft's VS Series reported a warning, a very standard extension. )
The reason the struct uses the length array of 0 or 1 at last, is mainly for the convenience of managing memory buffers, if you use pointers directly instead of arrays, then when you allocate memory buffers, you must allocate the struct once, and then assign the pointer in the struct once, (and the memory allocated at this time is not contiguous with the structure of the memory, so to manage the application and release) and if the use of arrays, then only one can be allocated all at once, (see the following example), in turn, the same as the release, using the array, once released, using pointers, you have to release the structure of the pointer, Release the structure again. You can't reverse the order.
is to allocate a continuous amount of memory to reduce the fragmentation of memory.
In a Linux system,/usr/include/linux/if_pppox.h has such a structure:
struct Pppoe_tag { __u16 tag_type; __u16 Tag_len; Char tag_data[0];} __attribute ((packed));
The last member is a variable-length array, which is best defined in this way for the structure of the TLV (type-length-value) Form or for other structures that require variable lengths. Very convenient to use, when created, malloc a structure size plus variable length of data length of the space to it, variable-length parts can be accessed as an array, release, the entire structure can be free. Examples are as follows:
struct Pppoe_tag *sample_tag;__u16 Sample_tag_len = 10;sample_tag = (struct Pppoe_tag *) malloc (sizeof (struct Pppoe_tag) + sizeof (char) *sample_tag_len); sample_tag->tag_type = 0xffff;sample_tag->tag_len = sample_tag_len;sample_tag- >tag_data[0]= .....
When released:
Free (Sample_tag);
Can I replace it with Char *tag_data? In fact it and Char *tag_data is a big difference, in order to illustrate this problem, I wrote the following program:
struct tag1{int a;int b;} __attribute ((packed)); struct tag2{ int A; int b; char *c;} __attribute ((packed)); struct tag3{ int A; int b; Char c[0];} __attribute ((packed)); struct tag4{ int A; int b; Char c[1];} __attribute ((packed));
From the above program and running results can be seen: Tag1 itself consists of two 32-bit integers, so accounted for 8 bytes of space. The TAG2 consists of two 32-bit integers, plus a char * pointer, so it takes 12 bytes. Tag3 is really see the difference between Char C[0] and Char *c, Char c[0] in C is not a pointer, is an offset, this offset points to a, B immediately after the space, so it actually does not occupy any space. Tag4 adds to this point in more details. Therefore, the last member of the above struct Pppoe_tag, if defined with Char *tag_data, would be inconvenient to use in addition to a pointer variable that would take up more than 4 bytes.
two ways to achieve comparison
Method One, when created, you can first allocate a piece of memory for the struct Pppoe_tag, and then allocate the memory for Tag_data, so that in the release, the Tag_data occupied memory is released first, and then the memory occupied by the Pppoe_tag is released;
struct Pppoe_tag { __u16 tag_type; __u16 Tag_len; char *tag_data;} __attribute ((packed)); struct Pppoe_tag *sample_tag;__u16 Sample_tag_len = 10; method One: Sample_tag = (struct Pppoe_tag *) malloc (sizeof (struct pppoe_tag)); Sample_tag->tag_len = Sample_tag_len;sample_tag->tag_data = malloc (sizeof ( char) *sample_tag_len); Sample_tag->tag_data[0]= ... Release: Free (sample_tag->tag_data); sample_tag;
Method Two, when created, directly for the struct pppoe_tag allocation of a struct Pppoe_tag size plus tag_data memory, tag_data content to be initialized, to let Tag_data point strct pppoe_tag behind the memory.
struct Pppoe_tag { __u16 tag_type; __u16 Tag_len; Char tag_data[0];} __attribute ((packed)); struct Pppoe_tag *sample_tag;__u16 Sample_tag_len = 10;sample_tag = (struct Pppoe_tag *) malloc ( sizeof (struct Pppoe_tag) +sizeof (char) *sample_tag_len); Sample_tag->tag_len = Sample_tag_len;sample_tag->tag_ Data = ((char *) sample_tag) +sizeof (struct pppoe_tag); sample_tag->tag_data[0]= ... Release: Free (Sample_tag), so it is convenient to use the definition of char tag_data[0] no matter which method is used.
The last length of the struct is 0 or 1 arrays--0 long arrays