How to pass union as function parameter

This code is for the driver for the DAC .

I have a bitcode below, which is a 24 bit register. So what I need to do is fill in the bitfield and write it to SPI on the chip.

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; 

In my initialization function, I create a union as shown below.

  union{ GAIN_REG_st GAIN_st; uint32_t G_32; } G_u; 

Now I need to pass the GAIN_REG_st bitfield to a function that will fill it.

After filling in, I can assign a bit-bit to a 32-bit integer and pass that integer to a low-level function for recording by SPI.

How do I pass a bitwise GAIN_REG_st value to a function when it is inside a union? (Can you show the function prototype and call)?

How does a function access bitfield members? (would that be like G_u.GAIN_st.rdwr_u8 = 1 ?)

+4
source share
5 answers
 union G_u the_union; the_union.GAIN_st.address_u8 = 0x4; function_call( &the_union ); void function_call( union G_u *the_union ) { uint8 address; address = the_union->GAIN_st.address_u8; return; } 

Do you mean this? this is a union, so why skip the inner member? it will not make any difference. They all start with the same memory offset.

+5
source

The name is about the transfer of the association, but the question asks about the passage of the structure. You can also do this: you simply declare the argument of the function appropriately and pass in a member or the whole union.

All current answers demonstrate passing by reference, but there is no need to do this, you can transfer it with a copy, which for a structure or union, which as a result has a 32-bit value, is not more expensive and saves dereferencing in the called function, therefore it can be more efficient;

 void fn( union G_u arg ); int main() { union G_u param; ... fn( param ); } 

or pass structure:

 void fn( GAIN_REG_st arg ); int main() { GAIN_REG_st param; ... fn( param ); } 

Note that you can type union, as you have a structure:

 typedef union { GAIN_REG_st GAIN_st; uint32_t G_32; } G_u ; 

then the first example will be simple:

 void fn( G_u arg ); int main() { G_u param; ... fn( param ); } 

There is almost certainly no difference in overhead between the transfer of structure or association. It is simply a question of where you choose to disclose your knowledge of inner representation.

+3
source

Prototype:

 int populateGainRegSt(GAIN_REG_st *st); 

The function can access the fields of the structure using the operator -> :

 st->data_u8 = 1; 

Using:

 G_u g; ... populateGainRegSt( &(g.GAIN_st)); 
+1
source
 #include <stdint.h> #include <stdio.h> 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; union G_u { GAIN_REG_st GAIN_st; uint32_t G_32; }; static void foo (GAIN_REG_st *data) { printf ("%x %x %x\n", data->rdwr_u8, data->not_used_u8, data->address_u8); } int main () { union G_u udata; udata.G_32 = 1986; foo (&udata.GAIN_st); return 0; } 
0
source

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) { /* implement rdwr_u8==1 here */ } else { /* implement rdwr_u8==1 here */ } } 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; } 
0
source

All Articles