10

Please Note: This question is not a duplicate of ( One element array in struct )

The following code is excerpted from the Linux kernel source (version: 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];
};

I just wonder why close_on_exec_init and open_fds_init are defined as arrays containing one element, rather than just defined as unsigned long close_on_exec_init; and unsigned long open_fds_init;.

Community
  • 1
  • 1
xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • also good explanation [here](http://stackoverflow.com/questions/6390331/why-use-array-size-1-instead-of-pointer) – quantdev Jun 04 '14 at 04:17
  • 2
    It seems like it can't possibly be a hack for flexible arrays since the array members aren't at the end. – Brian Bi Jun 04 '14 at 04:18
  • The post given above is different from this question. And the answer does not apply to this question. – xmllmx Jun 04 '14 at 04:18
  • @xmllmx Can you explain how your question is different? – Code-Apprentice Jun 04 '14 at 04:19
  • 3
    @Code-Guru, the number of array fields are more than one, and not the last fields. – xmllmx Jun 04 '14 at 04:21
  • [Here is the patch](https://lkml.org/lkml/2006/1/3/500) that introduced this, pretty much. Originally something to do with saving space on embedded platforms... I will leave it to others to figure out the details – Nemo Jun 04 '14 at 04:45

2 Answers2

6

These fields are an optimization so Linux doesn't have to perform as many allocations for a typical process that has no more than BITS_PER_LONG open file descriptors.

The close_on_exec_init field provides the initial storage for fdt->close_on_exec when a files_struct is allocated. (See dup_fd in fs/file.c.)

Each bit of fdt->close_on_exec is set if the corresponding file descriptor has the “close-on-exec” flag set. Thus Linux only needs to allocate additional space for fdt->close_on_exec if the process has more open file descriptors than the number of bits in an unsigned long.

The open_fds_init field serves the same function for the fdt->open_fds field. The fd_array field serves the same function for the fdt->fd field. (Note that fd_array has a size of BITS_PER_LONG.)

The close_on_exec_init and open_fds_init fields formerly had type struct embedded_fd_set, but were changed to bare arrays in this commit. The commit message doesn't explain why the author chose to use one-element arrays instead of bare scalars. Perhaps the author (David Howells) simply wanted to avoid using the & operator.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
2

My best guess: The addresses of these fields are used much more often than their actual values. In this case, making them size-1 arrays saves typing & every time their address is needed, since in C using the name of an array in an expression is in nearly all cases exactly equivalent to taking the address of its first element:

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

(As others have pointed out in the comments, it can't be that the fields are being used as a hack for variable-length arrays, since there is more than one and they don't appear at the end of the struct.)

[EDIT: As pointed out by user3477950, an array name is not always identical to the address of its first element -- in certain contexts, like the argument to sizeof, they mean different things. (That's the only context I can think of for C; in C++, passing an array name as an argument can also enable a template parameter's type to be inferred to be a reference type.)]

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
  • 3
    "using the name of an array in an expression is exactly equivalent to taking the address of its first element" - no, they are not exactly equivalent (think `sizeof` et al.), it would be better explain that an array name may decay into a pointer to its first element in some contexts. – The Paramagnetic Croissant Jun 04 '14 at 04:45