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

96

Я просматривал файлы заголовков своего микроконтроллера 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массивом с одним членом (этой анонимной структуры), но я не могу представить, для чего он используется. Любые идеи?

Александр - Восстановить Монику
источник
5
Может быть, что-то связано с превращением в указатель?
Элазар
3
Последний комментарий кажется совершенно неправильным ...
R .. GitHub ПРЕКРАТИТЕ ПОМОЩЬ ICE

Ответы:

116

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

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

ShadowRanger
источник
12
Это также предотвращает копирование через =.
melpomene
11
Это грубо. Я приму этот ответ, когда истечет минимальное время. Спасибо за вашу помощь!
Александр - Восстановить Монику
3
@Alexander: Это не так уж плохо, когда инкапсулируется с помощью typedefвот такого. Да, делать это специальным образом было бы ужасно, но если у вас есть слегка непрозрачный тип, когда пользователю API никогда не нужно думать о семантике ссылки и не ссылочной (она всегда должна передаваться по ссылке), это разумный способ о добавлении семантики автоматической ссылки к языку, в котором она отсутствует. Он работает даже в том случае, если пользователь пишет свои собственные API-интерфейсы, которые получают тип, потому что в C объявление о том, что вы принимаете массив в качестве аргумента, действительно означает, что вы принимаете указатель; все "просто работает".
ShadowRanger 03
4
@ShadowRanger Это умный трюк, но ... otherwise lacks itвот что в нем мерзости . Ограничения C, а не сам обходной путь
Александр - Reinstate Monica
34
ИМО это мерзко. Когда я впервые работал с GMP, я не мог понять, как это работает, поскольку числа явно передавались по значению. Мне пришлось покопаться в заголовках GMP, чтобы понять это. Это просто бросает вызов людям, которые действительно уже знают C. Затем вы должны мысленно отслеживать, какие параметры передаются по значению, а какие являются ссылочными, а не просто искать *в коде.
MM