Яка мета цього [1] в кінці декларації struct?


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 */

Я розумію, що він оголошує анонімну структуру і вводить це jmp_buf, але я не можу зрозуміти, для чого [1]це. Я знаю, що він оголошує jmp_bufмасив з одним членом (цієї анонімної структури), але я не уявляю, для чого він використовується. Якісь ідеї?


5
Щось пов’язане з розпадом покажчика, можливо?
Елазар

3
Остаточний коментар видається абсолютно неправильним ...
R .. GitHub СТОП ДОПОМОГАЙ ЛЕД

Відповіді:


115

Це загальний трюк для створення "посилального типу" на мові C, де використання його як аргументу функції призводить до того, що масив одного елемента переходить до покажчика на свій перший елемент без необхідності програмісту явно використовувати &оператор для отримання його адреси. Там, де оголошено, це реальний тип стека (не потрібно динамічного розподілу), але коли передається як аргумент, викликана функція отримує на неї вказівник, а не копію, тому вона передається дешево (і може бути змінена викликаною функцією, якщо ні const).

GMP використовує той самий трюк зі своїм mpz_tтипом, і це критично важливо, оскільки структура управляє покажчиком на динамічно виділену пам'ять; mpz_initфункція розраховує отримати покажчик на структуру, а не його копію, або він не може звернутися до його взагалі. Подібним чином багато операцій можуть змінити розмір динамічно виділеної пам'яті, і це не спрацювало б, якщо б вони не змогли змінити структуру абонента.


12
Це також запобігає копіюванню через =.
мельпомена

11
Це грубо. Я прийму цю відповідь, коли пройде мінімальний час. Спасибі за вашу допомогу!
Олександр - Відновити Моніку

3
@Alexander: Це не зовсім грубо, якщо інкапсулювати за допомогою typedefподібного. Так, робити це ad hoc було б якось жахливо, але якщо у вас ледь помітний непрозорий тип, коли користувачеві API ніколи не потрібно думати про посилання та нереференційну семантику (це завжди має передаватися за посиланням), це розумний спосіб додавання автоматичної посилальної семантики до мови, якої в іншому випадку не вистачає. Це навіть працює, якщо користувач пише власні API, які отримують тип, тому що в C заявляючи, що ви приймаєте масив як аргумент, насправді означає, що ви приймаєте покажчик; все "просто працює".
ShadowRanger

4
@ShadowRanger Це розумний фокус, але ... otherwise lacks itце те, що в цьому грубе. Обмеження С, а не саме обхідне рішення
Олександр - Відновити Моніку

34
ІМО це грубо. Вперше працюючи з GMP, я не міг зрозуміти, як це працює, оскільки цифри, очевидно, передавалися за значенням. Мені довелося копатись у заголовках GMP, щоб загадати. Це просто летить в обличчя людям, які насправді вже знають С. Тоді ви повинні відстежувати ментальні параметри, які параметри передаються за значенням, а які є посилальними, а не просто шукати *в коді.
М.М.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.