C语言 为什么这样的结构体包含两个数组字段,其中只包含一个元素?



请注意:这个问题不是 (struct中的一个元素数组)

的重复

以下代码摘自Linux内核源代码(版本:3.14)

struct files_struct
{
    atomic_t count;
    struct fdtable __rcu *fdt;
    struct fdtable fdtab;
    spinlock_t file_lock ____cacheline_aligned_in_smp;
    int next_fd;
    unsigned long close_on_exec_init[1];
    unsigned long open_fds_init[1];
    struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

我只是想知道为什么close_on_exec_initopen_fds_init被定义为包含一个元素的数组,而不是仅仅定义为unsigned long close_on_exec_init;unsigned long open_fds_init;

这些字段是一种优化,因此Linux不必为一个不超过BITS_PER_LONG个打开的文件描述符的典型进程执行那么多的分配。

当分配files_struct时,close_on_exec_init字段为fdt->close_on_exec提供初始存储空间。(参见fs/file.c中的dup_fd)

如果相应的文件描述符设置了"close-on-exec"标志,则设置fdt->close_on_exec的每个位。因此,只有当进程的打开文件描述符多于unsigned long中的位数时,Linux才需要为fdt->close_on_exec分配额外的空间。

open_fds_init字段的功能与fdt->open_fds字段相同。fd_arrayfdt->fd的作用相同。(注意fd_array的大小为BITS_PER_LONG)

close_on_exec_initopen_fds_init字段以前的类型是struct embedded_fd_set,但在这次提交中被更改为裸数组。提交消息没有解释为什么作者选择使用单元素数组而不是纯标量。也许作者(David Howells)只是想避免使用&运算符。

我最好的猜测是:这些字段的地址比它们的实际值使用得更频繁。在这种情况下,将它们设置为大小为1的数组,节省了每次需要它们的地址时输入&的时间,因为在C语言中,在表达式中使用数组的名称几乎在所有情况下都完全等同于接受其第一个元素的地址:

int x;
int y[1];
function_that_needs_address_of_int(&x);
function_that_needs_address_of_int(y);
function_that_needs_address_of_int(&y[0]);    // Identical to previous line

(正如其他人在评论中指出的那样,字段不可能被用作变长数组的hack,因为有多个字段,并且它们不出现在struct的末尾。)

[EDIT:]正如user3477950所指出的,数组名并不总是与其第一个元素的地址相同——在某些上下文中,比如sizeof的参数,它们意味着不同的东西。(这是我能想到的C的唯一上下文;>

最新更新