大小为零的指针数组是什么意思?

What does it mean to have a zero sized array of pointers?

我在 linux 内核源代码 (net/ipv4/fib_trie.c)-

中看到了一个看起来像这样的 struct 的定义
 
struct key_vector {
    t_key key;
    unsigned char pos;      /* 2log(KEYLENGTH) bits needed */
    unsigned char bits;     /* 2log(KEYLENGTH) bits needed */
    unsigned char slen;
    union {
        /* This list pointer if valid if (pos | bits) == 0 (LEAF) */
        struct hlist_head leaf;
        /* This array is valid if (pos | bits) > 0 (TNODE) */
        struct key_vector __rcu *tnode[0];
    };
};

上面tnode的定义是什么意思?我写了一个示例代码来理解和打印看起来像 -


struct s {
    union {
        int i;
        int *pi[0];
    };
};

int main()
{
    struct s s1;
    s1.i = 0x12345678;

    printf("sizeof(s1): %lu, s1.i: %x, s1.pi: %p, s1.*pi: %p\n", sizeof(s1), s1.i, s1.pi[0], s1.pi);
}

其输出为-

sizeof(s1): 8, s1.i: 12345678, s1.pi: 0x7ffc12345678, s1.*pi: 0x7ffc2824add0

我不确定我是否理解这一点。

这是一种常见的做法,称为“struct hack”或灵活的数组成员。为结构分配内存时,添加额外的 space。然后可以使用结构末尾的数组成员访问额外的 space 。从 C99 开始,您可以完全忽略大小。

在批准 C89 之前,许多编译器会将结构中的 someType member[someConst]; 之类的声明解释为将“下一项偏移量”推进到 someType 对齐要求的倍数,关联具有该偏移量的符号 member,将 someConst 解释为无符号数,然后将“下一个成员偏移量”推进 someConst * sizeof someType。他们会以这种方式行事 ,而不考虑 someConst 是否为零。因为一些程序依赖于编译器以这种方式处理零长度数组声明,但委员会的一些成员不想要求所有编译器都支持它们,所以标准的作者选择说实现可能支持零长度数组或不是,在他们闲暇时,前提是当提供任何利用零大小数组的程序时,他们至少会发出一个诊断(程序员在使用有效支持该构造的实现时可以在闲暇时忽略)。