结构数组末尾的空括号'{}'有什么用?

What is the need of empty braces '{ }' at the end of array of structs?

我在 Linux 内核中打了一些 code:

static struct ctl_table ip_ct_sysctl_table[] = {
    {
        .procname   = "ip_conntrack_max",
        .maxlen     = sizeof(int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec,
    },
    // ...
    {
        .procname   = "ip_conntrack_log_invalid",
        .maxlen     = sizeof(unsigned int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec_minmax,
        .extra1     = &log_invalid_proto_min,
        .extra2     = &log_invalid_proto_max,
    },
    { }
};

此处的结构数组以 { } 结尾。添加它的目的是什么?
顺便说一下,在这段代码的上方还有一个 array of structs,但末尾没有空括号。

什么时候应该在结构数组的末尾使用空括号?

您可能熟悉以零结尾的字符串。 ctl_table ip_ct_sysctl_table[] 是一个以零结尾的数组,即最后一个数组条目具有全零成员。

在数组的末尾初始化一个零元素,以便将数组的元素数增加一个。

考虑这个小演示:

#include <stdio.h>

struct Test
{
  int x;
  int y;
} arr[] =
{
    {1,2},
    {3,4},
//  {}
};

int main(void) {
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

如果您取消注释数组初始化列表末尾的 {}arr 数组的大小将会改变。

输出:

With // {}(数组有 2 个元素)

2

With {}(数组有 3 个元素)

3

进一步说明:

ip_ct_sysctl_table数组只用在一个地方,就是这里:

in->ctl_table = kmemdup(ip_ct_sysctl_table,
                sizeof(ip_ct_sysctl_table),
                GFP_KERNEL);

额外的 {} 增加了总大小 ip_ct_sysctl_table

此特定更改是 Eric W. Biederman 提交的 sysctl net: Remove unused binary sysctl code 的一部分,将 ip_ct_sysctl_table 数组最后一个元素的初始化从 {0} 更改为 {}(并对许多其他数组初始化执行类似的更改)。

{0} 模式似乎已经存在了很长时间,而且 {0}{} 最终元素初始化都很常见(在 Linux 源代码中code) 明确称为 Terminating entry,因此很可能存在一种模式,允许在不知道其长度的情况下使用这些数组,在命中零初始化的终止条目时终止使用。例如。对于 sound/aoa/fabrics/snd-aoa-fabric-layout.c 中的类似数组,零初始化的意图甚至在评论中明确提及,例如:

static struct codec_connection toonie_connections[] = {
  {
      .connected = CC_SPEAKERS | CC_HEADPHONE,
      .codec_bit = 0,
  },
  {} /* terminate array by .connected == 0 */
};

What is the need of empty braces '{ }' at the end of array of structs?

需要说明的是:"empty braces '{ }' at the end of array of structs" 不需要 来满足 C 语法要求。

When should I use empty braces at the end of an array of structs?

当代码需要 sentinel value.

有时 有用 程序的最终数组元素全为零 - 当然可以检测结束。 需要来自应用程序对数组ctl_table ip_ct_sysctl_table[]的使用,而不是来自C语言的需要。