What is the need of empty braces '{ }' at the end of array of structs?
CArraysStructLinux KernelC Problem Overview
I hit some [tag:c] code in Linux kernel:
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,
},
{ }
};
Here an array of structs ends with { }
. For what purpose was it added?
By the way, a bit above this code there is another array of structs, but without empty braces at the end.
When should I use empty braces at the end of an array of structs?
C Solutions
Solution 1 - C
This particular change was part of the sysctl net: Remove unused binary sysctl code commit by Eric W. Biederman, changing the initialization of the last element of the ip_ct_sysctl_table
array from {0}
to {}
(and performs similar changes to many other array initializations).
The {0}
pattern seems to have been around for much longer though, and both {0}
or {}
final element-initialization is commonly (in the Linux source code) explicitly referred to as Terminating entry
, so it is likely a pattern present to allow consuming these arrays without knowing their lengths, terminating consumption when hitting the zero-initialized terminating entry. E.g. for the similar arrays in sound/aoa/fabrics/snd-aoa-fabric-layout.c
the intent of the zero-initialization is even explicitly mentioned in a comment, e.g.:
> static struct codec_connection toonie_connections[] = { > { > .connected = CC_SPEAKERS | CC_HEADPHONE, > .codec_bit = 0, > }, > {} /* terminate array by .connected == 0 */ > };
Solution 2 - C
You're probably familiar with zero-terminated strings. ctl_table ip_ct_sysctl_table[]
is a zero-terminated array, i.e. the last array entry has all-zero members.
Solution 3 - C
> What is the need of empty braces '{ }' at the end of array of structs?
To be clear: the "empty braces '{ }' at the end of array of structs" is not needed to satisfy C syntax requirements.
> When should I use empty braces at the end of an array of structs?
When code wants a sentinel value.
It is sometimes useful for the program to have a final array element of all zeros - certainly to detect the end. The need comes from the application's use of array ctl_table ip_ct_sysctl_table[]
, not from a C language need.
Solution 4 - C
It's one zero initialized element at the end of the array in order to increase the number of elements of the array by one.
Consider this small demo:
#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;
}
The size of the arr
array will change if you uncomment the {}
at the end of the array initialisation list.
Outputs:
With // {}
(array has 2 elements)
2
With {}
(array has 3 elements)
3
Further explanation:
The ip_ct_sysctl_table
array is only used at one place, that is here:
in->ctl_table = kmemdup(ip_ct_sysctl_table,
sizeof(ip_ct_sysctl_table),
GFP_KERNEL);
The extra {}
increases the total size ip_ct_sysctl_table
.