I was snooping through my MSP430 microcontroller's header files, and I ran into this in <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 */
I understand that it declares an anonymous struct and typedef's it to jmp_buf
, but I can't figure out what the [1]
is for. I know it declares jmp_buf
to be an array with one member (of this anonymous struct), but I can't imagine what it's used for. Any ideas?
This is a common trick to make a "reference type" in C, where using it as a function argument causes the single element array to degrade to a pointer to its first element without the programmer needing to explicitly use the &
operator to get its address. Where declared, it's a real stack type (no dynamic allocation needed), but when passed as an argument, the called function receives a pointer to it, not a copy, so it's passed cheaply (and can be mutated by the called function if not const
).
GMP uses the same trick with its mpz_t
type, and it's critical there, because the structure manages a pointer to dynamically allocated memory; the mpz_init
function relies on getting a pointer to the structure, not a copy of it, or it couldn't initialize it at all. Similarly, many operations can resize the dynamically allocated memory, and that wouldn't work if they couldn't mutate the caller's struct.