要素がゼロの配列が必要な理由は何ですか? 質問する

要素がゼロの配列が必要な理由は何ですか? 質問する

Linux カーネル コードで、理解できない次の点を見つけました。

 struct bts_action {
         u16 type;
         u16 size;
         u8 data[0];
 } __attribute__ ((packed));

コードはこちらです:http://lxr.free-electrons.com/source/include/linux/ti_wilink_st.h

要素がゼロのデータ配列の必要性と目的は何ですか?

ベストアンサー1

mallocこれは、 (この場合は) を 2 回呼び出すことなく、可変サイズのデータ​​を取得する方法ですkmalloc。次のように使用します。

struct bts_action *var = kmalloc(sizeof(*var) + extra, GFP_KERNEL);

This used to be not standard and was considered a hack (as Aniket said), but it was standardized in C99. The standard format for it now is:

struct bts_action {
     u16 type;
     u16 size;
     u8 data[];
} __attribute__ ((packed)); /* Note: the __attribute__ is irrelevant here */

Note that you don't mention any size for the data field. Note also that this special variable can only come at the end of the struct.


In C99, this matter is explained in 6.7.2.1.16 (emphasis mine):

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. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

Or in other words, if you have:

struct something
{
    /* other variables */
    char data[];
}

struct something *var = malloc(sizeof(*var) + extra);

You can access var->data with indices in [0, extra). Note that sizeof(struct something) will only give the size accounting for the other variables, i.e. gives data a size of 0.


It may be interesting also to note how the standard actually gives examples of mallocing such a construct (6.7.2.1.17):

struct s { int n; double d[]; };

int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

Another interesting note by the standard in the same location is (emphasis mine):

assuming that the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if p had been declared as:

struct { int n; double d[m]; } *p;

(there are circumstances in which this equivalence is broken; in particular, the offsets of member d might not be the same).

おすすめ記事