Apa tujuan [1] ini di akhir deklarasi struct?

96

Saya mengintip melalui file header mikrokontroler MSP430 saya, dan saya menemukan ini di <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 */

Saya mengerti bahwa itu mendeklarasikan struct anonim dan typedef itu ke jmp_buf, tetapi saya tidak tahu untuk apa [1]. Saya tahu itu mendeklarasikan jmp_bufsebagai array dengan satu anggota (dari struct anonim ini), tetapi saya tidak dapat membayangkan untuk apa itu digunakan. Ada ide?

Alexander - Kembalikan Monica
sumber
5
Mungkin ada hubungannya dengan membusuk menjadi penunjuk?
Elazar
3
Komentar terakhir tampaknya sama sekali salah ...
R .. GitHub STOP HELPING ICE

Jawaban:

116

Ini adalah trik umum untuk membuat "tipe referensi" di C, di mana menggunakannya sebagai argumen fungsi menyebabkan larik elemen tunggal terdegradasi ke penunjuk ke elemen pertamanya tanpa pemrogram perlu secara eksplisit menggunakan &operator untuk mendapatkan alamatnya. Di mana dideklarasikan, ini adalah tipe tumpukan nyata (tidak diperlukan alokasi dinamis), tetapi ketika diteruskan sebagai argumen, fungsi yang dipanggil menerima penunjuk ke sana, bukan salinan, jadi itu diteruskan dengan murah (dan dapat dimutasi oleh fungsi yang dipanggil jika tidak const).

GMP menggunakan trik yang sama dengan mpz_ttipenya, dan sangat penting di sana, karena struktur mengelola penunjuk ke memori yang dialokasikan secara dinamis; yang mpz_initfungsi bergantung pada mendapatkan pointer ke struktur, bukan salinan itu, atau tidak bisa menginisialisasi sama sekali. Demikian pula, banyak operasi dapat mengubah ukuran memori yang dialokasikan secara dinamis, dan itu tidak akan berfungsi jika mereka tidak dapat mengubah struct pemanggil.

ShadowRanger
sumber
12
Ini juga mencegah penyalinan melalui =.
melpomene
11
Menjijikkan. Saya akan menerima jawaban ini setelah waktu minimum berlalu. Terima kasih atas bantuan Anda!
Alexander - Kembalikan Monica
3
@Alexander: Ini tidak terlalu kotor ketika dikemas melalui typedefseperti ini. Ya, melakukan ad-hoc ini akan sangat buruk, tetapi jika Anda memiliki jenis yang agak buram, di mana pengguna API tidak perlu memikirkan tentang semantik referensi vs. non-referensi (harus selalu melewati referensi), itu adalah cara yang masuk akal menambahkan semantik referensi otomatis ke bahasa yang tidak memiliki bahasa tersebut. Ia bahkan bekerja jika pengguna menulis API mereka sendiri yang menerima tipe, karena di C, menyatakan Anda menerima sebuah array sebagai argumen berarti Anda menerima sebuah pointer; semuanya "berjalan lancar".
ShadowRanger
4
@ShadowRanger Ini adalah trik yang cerdas, tapi ... otherwise lacks ityang menjijikkan tentang itu. Batasan C, bukan solusi itu sendiri
Alexander - Reinstate Monica
34
IMO itu menjijikkan. Pertama kali bekerja dengan GMP, saya tidak dapat memahami cara kerjanya karena angka-angka tampaknya diteruskan oleh nilai. Saya harus menggali header GMP untuk memecahkannya. Itu hanya terbang di wajah orang-orang yang sebenarnya sudah tahu C. Kemudian Anda harus terus melacak parameter mana yang dilewatkan oleh nilai dan mana yang menjadi referensi alih-alih hanya mencari *dalam kode.
MM