在结构数组末尾有空括号“ {}”有什么需要?

时间:2020-03-02 13:03:02

标签: c arrays struct linux-kernel

我在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,但最后没有空括号。

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

4 个答案:

答案 0 :(得分:39)

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

尽管{0}模式似乎已经存在了很长时间,并且{0}{}的最终元素初始化通常(在Linux源代码中)都明确地称为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 */
};

答案 1 :(得分:21)

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

答案 2 :(得分:13)

在结构数组的末尾需要空括号'{}'是什么?

要清楚:不需要满足C语法要求的“结构数组末尾的空括号'{}'”。

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

代码需要sentinel value时。

对于程序来说,最终的数组元素全为零有时是很有用的-当然可以检测结束。 需求来自应用程序对数组ActivityTaskManager.getService().dismissKeyguard( activity.getActivityToken(), new IKeyguardDismissCallback.Stub() { @Override public void onDismissError() throws RemoteException { if (callback != null && !activity.isDestroyed()) { activity.mHandler.post(callback::onDismissError); } } @Override public void onDismissSucceeded() throws RemoteException { if (callback != null && !activity.isDestroyed()) { activity.mHandler.post(callback::onDismissSucceeded); } } @Override public void onDismissCancelled() throws RemoteException { if (callback != null && !activity.isDestroyed()) { activity.mHandler.post(callback::onDismissCancelled); } } }, message); 的使用,而不是来自C语言的需求。

答案 3 :(得分:9)

它是数组末尾的一个零初始化元素,目的是将数组中的元素数增加一。

考虑这个小演示:

#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的注释,则{}数组的大小将改变。

输出:

使用// {}(数组包含2个元素)

2

使用{}(数组包含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