如何将联合作为参数传递给函数
此代码适用于 DAC 芯片的驱动程序。
下面有一个位字段,代表 24 位寄存器。所以我需要做的是填充位字段并通过 SPI 将其写入芯片。
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{
GAIN_REG_st GAIN_st;
uint32_t G_32;
} G_u;
现在我需要将 GAIN_REG_st 位字段传递给将填充它的函数。
填充后,我可以将位字段分配给 32 位整数,并将该整数传递给低级函数以通过 SPI 进行写入。
当位域 GAIN_REG_st 位于联合内部时,如何将位域 GAIN_REG_st 传递给函数? (你能展示一个函数原型并调用)吗?
该函数如何访问位域的成员? (会像G_u.GAIN_st.rdwr_u8 = 1
吗?)
This code is for a driver for a DAC chip.
I have a bitfield below which represents a 24-bit register. So what I need to do, is populate the bitfield and write it out over SPI to 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 initialisation function I create a union as below.
union{
GAIN_REG_st GAIN_st;
uint32_t G_32;
} G_u;
Now I need to pass a GAIN_REG_st bitfield to a function which will populate it.
Once it's populated I can assign the bitfield to a 32-bit integer and pass that integer to a low level function to write over SPI.
How do I pass the bitfield GAIN_REG_st to a function when it's inside a union? (Can you show a function prototype and call)?
How does the function access the bitfield's members? (would it be like G_u.GAIN_st.rdwr_u8 = 1
?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你是这个意思吗?既然是工会,为什么要通过内部成员呢?这不会有任何区别。它们都以相同的内存偏移量开始。
Do you mean this? it's a union, so why pass an internal member? it won't make any difference. They all start at the same memory offset.
标题是关于传递联合,但问题是关于传递结构。您可以执行任一操作,只需相应地声明函数参数并传递成员或整个联合。
当前的所有答案都演示了通过引用传递,但没有必要这样做,您可以通过复制传递,这对于最终是 32 位值的结构或联合来说并不更昂贵,并且可以在被调用函数中保存取消引用,因此可能会更有效率;
或传递结构:
请注意,您可以在拥有结构时键入定义联合:
那么第一个示例将很简单;
几乎可以肯定,传递结构体或联合体之间的开销没有区别。这只是您选择在哪里公开内部表示知识的问题。
The title is about passing the union, but the question asks about passing structure. You can do either, you simply declare the function argument accordingly and pass either the member or the whole union.
All the current answers demonstrate passing by reference, but there is no need to do that, you can pass by copy, which for a struct or union that is ultimately a 32bit value is no more expensive and saves a dereferencing in the called function, so may be more efficient;
or to pass the structure:
Note that you could typedef the union as you have the struct:
then the first example would be simply;
There will almost certainly be no difference in overhead between passing the struct or the union. It is just a matter of where you choose to expose knowledge of the internal representation.
原型:
该函数可以使用
->
运算符访问结构体字段:用法:
Prototype:
The function may access the structure fields using
->
operator:Usage:
C89 没有真正规定直接初始化和传递联合作为参数。在 C89 中,联合只能使用变量或变量引用来声明,然后必须使用变量进行初始化。但是,您可以按值传递和返回这些变量,因此无需使用指针。
返回的结构和联合不需要像普通返回参数一样适合寄存器。在这种情况下,编译器会为您做所有事情(在堆栈上),如果它是深度优化和内联的,这通常不会涉及太多开销(阅读:仔细手工优化的 C 代码可能会更快,但是优化器通常会做相当多的事情)好工作)。
下面是示例代码。
使用实用函数
create_GAIN_REG_st
和GAIN_REG_st_to_G_u
,您可以在调用函数的参数列表上动态创建结构体/联合,该函数接受这些作为参数)。请注意,这种方式仅适用于非指针类型,因为指针必须指向某个地方。如果使用指针,则需要
malloc
/free
。但是,通过返回整个数据类型,您就不需要它了。一件重要的事情是,您可以获得指向动态创建的数据的指针,但数据仅在调用期间存在,就像堆栈上的变量一样 - 这可能很快导致“释放后使用”或别名为重新的指针- 使用的堆栈区域。 (因此,始终避免指向作为参数传递的结构/联合的指针,这些指针会被返回或临时变量。)现在您可以直接调用您的函数
spi
:当然,您可以展平双重调用:
或者您可以创建一个专门的函数:
C89 has no real provision for initializing and passing unions as arguments directly. In C89 Unions can only be declared using variable or variable references and then must be initialized using the variable. However you then can pass and return these variables by value, so without using pointers.
Returned structs and unions need not fit into registers like normal return parameters. In this case the compiler does everything for you (on the stack), and if it is deeply optimizing and inlined, this usually does not involve much overhead (read: Carefully hand optimized C code can be faster, however often the optimizer does a fairly good job).
Below is example code.
With the utility functions
create_GAIN_REG_st
andGAIN_REG_st_to_G_u
you can create the struct/union on the fly on the argument list to the call of your function, which is accepting these as parameter(s).Please note that this only works for non-pointer-types this way, as pointer must point somewhere. If you use pointers, you need to
malloc
/free
. But with returning the whole datatype you do not need that. 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 aliased to re-used stack regions. (So always avoid pointers to structs/unions which are passed as arguments, which are returned or which are temporary variables.)Now you can directly call your function
spi
:Of course you can flatten out the double call:
or you can create a specialized function: