C - 使用嵌套大小信息声明复合类型 [英] C - declare compound type with nested size info
问题描述
你好CP的同事,
作为尝试在两个μC之间来回传递消息的一部分,我创建了 Message_t 。要发送这样的消息,用户必须告诉发送功能,要传输多少字节。
我想为Message_t添加一条带有消息的符号在一个地方声明的类型只有和很容易告诉用户它在调用代码时的大小。
我尝试了什么:
GeneralMessage_t 和 ThermocontactMessage_t 的不同声明:
Hello fellow CPians,
as part of an attempt to pass messages back and forth between two µCs, I created Message_t. To send such a message, user has to tell the sending function, how many bytes to transfer.
I'd like to have a notation for Message_t that has a message type declared in one place only and is easily telling user its size in calling code.
What I have tried:
Different declarations of GeneralMessage_t and ThermocontactMessage_t here:
typedef struct ThermocontactMessage_t
{
uint32_t count;
uint8_t value:1;
}ThermocontactMessage_t; // Pro: Reachable by sizeof in calling code
// Con: Maintain here _and_ within union
typedef struct Message_t
{
MessageHeader_t hdr;
union
{
struct
{
void* data;
}GeneralMessage_t; // Pro: One place to maintain.
// Con: No size info in calling code.
struct
{
uint64_t value;
}TestMessage;
ThermocontactMessage_t ThermocontactMessage;
}content;
}Message_t;
/* Usage */
void SomeFunction(bool thermocontactState)
{
Message_t msg = {
.content.ThermocontactMessage.value = thermocontactState,
.content.ThermocontactMessage.count = ++messageCount,
.hdr.id = MessageType_Thermocontact,
.hdr.length = sizeof(ThermocontactMessage_t)
};
}
GeneralMessage_t 非常棒,因为它只需要在一个地方声明。另一方面, ThermocontactMessage_t 可供SomeFunction()中的 sizeof 运算符访问。
GeneralMessage_t is great because it needs to be declared only in one place. ThermocontactMessage_t, on the other hand, is accessible for the sizeof operator in SomeFunction().
推荐答案
I我不确定我是否理解你的问题。您面临的问题是您的所有消息都有一个共同的标题,然后是一些特定于类型的部分。要发送它们,您需要将这两个部分放在一个连续的缓冲区中。我想你有两个选择:
(1)在每种消息类型中包含标题,即
I am not sure that I understand your question correctly. The problem you are facing is that all your messages have a common header and then some type-specific part. And to send them you want both of these parts in a contiguous buffer. I guess you have two options here:
(1) Include the header in every message type, i.e.
typedef struct ThermocontactMessage_t
{
MessageHeader_t hdr;
uint32_t count;
uint8_t value:1;
}ThermocontactMessage_t;
(2)只需保留特定类型的结构,并在传输函数中构造一个带标题+消息的缓冲区: br />
(2) Just leave your type-specific structures as they are and construct a buffer with header + message in your transmit function:
typedef struct Message_t
{
MessageHeader_t hdr;
BYTE data[MAX_CARGO_SIZE];
}Message_t;
void SomeFunction(bool thermocontactState)
{
Message_t msg;
ThermocontactMessage_t* pData = (ThermocontactMessage_t*) msg.data;
// fill the header
msg.hdr.id = MessageType_Thermocontact,
msg.hdr.length = sizeof(ThermocontactMessage_t)
// fill the cargo part
pData->value = thermocontactState;
pData->count = ++messageCount;
...
}
对于很多消息类型,你最终会得到很多重复代码,可以通过使用填充标题的宏并将指针强制转换为数据部分来缓解。然后这个函数看起来像:
With many message types you are going to end-up with a lot of repetitive code, which can be mitigated by use of a macro that fills the header and casts a pointer to the data part. Then this function would look like:
void SomeFunction(bool thermocontactState)
{
Message_t msg;
ThermocontactMessage_t* pData = FILLHEADER (Thermocontact);
pData->value = thermocontactState;
pData->count = ++messageCount;
...
}
看起来好多了,避免了复制粘贴错误并保留了代码清洁。宏足够聪明,可以从其参数Thermocontact派生出消息类型-id是MessageType_Thermocontact,方法是预先添加MessageType_,并且消息结构是ThermocontactMessage_t,方法是附加Message_t。因此,通过一些宏观魔术你可以完成相当多的工作。当然,如果您可以使用C ++而不是C,那么所有这些都不是必需的。
That looks a lot nicer, avoids copy-paste errors and keeps your code clean. The macro is smart enough to derive from its argument Thermocontact that the message type-id is MessageType_Thermocontact by prepending MessageType_ and that the message structure is ThermocontactMessage_t by appending Message_t. Thus with a bit of macro-magic you can accomplish quite a bit. Of course, all of this would not be necessary if you could use C++ instead of C.
这篇关于C - 使用嵌套大小信息声明复合类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!