In C89, there is no real provision for initializing and passing joins as arguments directly. In C89, Unions can only be declared using variables or variable references, and then must be initialized using a variable. However, you can pass and return these variables by value, so without using pointers.
Returned structures and unions should not fit into registers, such as normal return parameters. In this case, the compiler does everything for you (on the stack), and if it is highly optimized and nested, it usually does not require significant overhead (read: carefully optimized C-code C can be faster, but often the optimizer does a pretty good job).
The following is sample code.
Using the utility functions create_GAIN_REG_st and GAIN_REG_st_to_G_u you can create a structure / union on the fly in the list of arguments to call your function, which takes them as parameter (s).
Note that this only works for types without pointers, as the pointer must point somewhere. If you use pointers you need malloc / free . But, returning the entire data type, you do not need it. One important thing is that you can get a pointer to the data created on the fly, but the data only lives during the call, as usual, for variables on the stack - this can quickly lead to "use after free" or pointers with an alias - Used areas of the stack. (Therefore, always avoid pointers to structures / joins that are passed as arguments that are returned or that are temporary variables.)
#define __inline__ /*if not using GCC*/ typedef struct { uint8_t rdwr_u8: 1; uint8_t not_used_u8: 3; uint8_t address_u8: 4; uint8_t reserved_u8: 8; uint8_t data_u8: 8; uint8_t padding_u8: 8; } GAIN_REG_st; typedef union { GAIN_REG_st GAIN_st; uint32_t G_32; } G_u; GAIN_REG_st __inline__ create_GAIN_REG_st(uint8_t rdwr, uint8_t address, uint8_t data) { GAIN_REG_st g = { 0 }; g.rdwr_u8 = rdwr; g.address_u8 = address; g.data_u8 = data; return g; } G_u __inline__ GAIN_REG_st_to_G_u(GAIN_REG_st g) { G_u u = { 0 }; u.GAIN_st = g; return u; }
Now you can directly call your spi function:
void spi(G_u u) { if (u.GAIN_st.rdwr_u8) { } else { } } int main() { spi(GAIN_REG_st_to_G_u(create_GAIN_REG_st(1,19,255))); return 0; }
Of course, you can smooth out the double call:
G_u __inline__ create_G_u_bits(uint8_t rdwr, uint8_t address, uint8_t data) { return GAIN_REG_st_to_G_u(create_GAIN_REG_st(rdwr, address, data)); } int main() { spi(create_G_u_bits(1,19,255)); return 0; }
or you can create a specialized function:
void spi_bits(uint8_t rdwr, uint8_t address, uint8_t data) { spi(GAIN_REG_st_to_G_u(create_GAIN_REG_st(rdwr, address, data))); } int main() { spi_bits(1,19,255); return 0; }