Какова цель этого [1] в конце объявления структуры?

Я просматривал свои файлы заголовков микроконтроллеров MSP430, и я столкнулся с этим в <setjmp.h>:

/* r3 does not have to be saved */
typedef struct
{
    uint32_t __j_pc; /* return address */
    uint32_t __j_sp; /* r1 stack pointer */
    uint32_t __j_sr; /* r2 status register */
    uint32_t __j_r4;
    uint32_t __j_r5;
    uint32_t __j_r6;
    uint32_t __j_r7;
    uint32_t __j_r8;
    uint32_t __j_r9;
    uint32_t __j_r10;
    uint32_t __j_r11;
} jmp_buf[1]; /* size = 20 bytes */

Я понимаю, что он объявляет анонимную структуру и typedef для jmp_buf, но я не могу понять, для чего нужен [1]. Я знаю, что объявляет jmp_buf как массив с одним членом (этой анонимной структуры), но я не могу представить, для чего он используется. Любые идеи?

Ответ 1

Это общий трюк, чтобы сделать "ссылочный тип" в C, где использование его в качестве аргумента функции приводит к тому, что один элементный массив деградирует к указателю на его первый элемент без необходимости программиста, явно использующего & оператора, чтобы получить его адрес. Если объявлено, это реальный тип стека (не требуется динамического выделения), но при передаче в качестве аргумента вызываемая функция получает указатель на него, а не копию, поэтому она прошла дешево (и может быть изменена вызываемой функцией, если нет const).

GMP использует тот же трюк со своим типом mpz_t, и он там критичен, потому что структура управляет указателем на динамически распределенную память; функция mpz_init полагается на получение указателя на структуру, а не на ее копию, или вообще не может ее инициализировать. Аналогичным образом, многие операции могут изменять размер динамически распределенной памяти, и это не сработает, если они не смогут изменить структуру вызывающего объекта.