Qual è lo scopo di questo [1] alla fine della dichiarazione struct?


96

Stavo curiosando tra i file di intestazione del mio microcontrollore MSP430 e mi sono imbattuto in questo <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 */

Capisco che dichiara una struttura anonima e typedef lo fa jmp_buf, ma non riesco a capire a cosa [1]serva. So che dichiara jmp_bufdi essere un array con un membro (di questa struttura anonima), ma non riesco a immaginare a cosa serva. Qualche idea?


5
Forse ha qualcosa a che fare con il decadere in pointer?
Elazar

3
Il commento finale sembra completamente sbagliato ...
R .. GitHub STOP AIUTO AL GHIACCIO

Risposte:


115

Questo è un trucco comune per creare un "tipo di riferimento" in C, dove usarlo come argomento di una funzione fa degradare l'array a singolo elemento a un puntatore al suo primo elemento senza che il programmatore debba usare esplicitamente l' &operatore per ottenere il suo indirizzo. Dove dichiarato, è un vero tipo di stack (non è necessaria alcuna allocazione dinamica), ma quando passata come argomento, la funzione chiamata riceve un puntatore ad essa, non una copia, quindi viene passato a buon mercato (e può essere mutato dalla funzione chiamata in caso contrario const).

GMP usa lo stesso trucco con il suo mpz_ttipo, ed è fondamentale, perché la struttura gestisce un puntatore alla memoria allocata dinamicamente; la mpz_initfunzione si basa sull'ottenere un puntatore alla struttura, non una copia di essa, o non potrebbe inizializzarla affatto. Allo stesso modo, molte operazioni possono ridimensionare la memoria allocata dinamicamente e ciò non funzionerebbe se non potessero modificare la struttura del chiamante.


12
Inoltre impedisce la copia tramite =.
melpomene

11
È disgustoso. Accetterò questa risposta una volta trascorso il tempo minimo. Grazie per l'aiuto!
Alexander - Ripristina Monica il

3
@Alexander: non è così disgustoso se incapsulato tramite un typedefsimile. Sì, fare questo ad hoc sarebbe un pò terribile, ma se hai un tipo leggermente opaco, in cui l'utente API non ha mai bisogno di pensare alla semantica di riferimento rispetto a quella non di riferimento (dovrebbe sempre passare per riferimento), è un modo ragionevole di aggiungere semantica di riferimento automatico a un linguaggio che altrimenti sarebbe privo di esso. Funziona anche se l'utente scrive le proprie API che ricevono il tipo, perché in C, dichiarare di accettare un array come argomento significa in realtà accettare un puntatore; tutto "funziona e basta".
ShadowRanger

4
@ShadowRanger È un trucco intelligente, ma ... otherwise lacks itè disgustoso. I limiti di C, non la soluzione alternativa in sé
Alexander - Reinstate Monica

34
IMO è schifoso. La prima volta che ho lavorato con GMP non riuscivo a capire come funzionasse poiché i numeri erano apparentemente passati per valore. Ho dovuto scavare nelle intestazioni GMP per risolverlo. Vola solo in faccia a persone che in realtà conoscono già C. Quindi devi tenere traccia mentale di quali parametri vengono passati per valore e quali sono di riferimento invece di cercare solo un *nel codice.
MM
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.