用值填充结构体 [英] struct fill with values

查看:41
本文介绍了用值填充结构体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在二进制协议中,我需要发送 8 个字节.这些字节可以包含 8 位或 16 位长的整数,也可以包含 1、2 或 3 位长的标志.

In a binary protocol I need to send 8 bytes. These bytes can contain integers that are 8 or 16 bit long, but also flags of 1, 2 or 3 bit length.

为了简化它,我更喜欢使用结构:

To simplify it, I'd prefer to use a struct:

struct MakeCoffeeCmd
{
    UINT8 sugar : 2;
    UINT8 milk : 1;
    UINT16 liters;
};

所以我可以这样使用它:

so I can use it like this:

cmd.sugar = 1;
cmd.milk = 0;
cmd.liters = 42;

send(cmd);

问题是:糖、牛奶和升在 8 字节数组中定义了位置,每个未使用的位都必须设置为 1.

Problem is: sugar, milk and liters have defined positions in the 8 byte array, every unused bit must be set to 1.

现在,我使用:

UINT8 cmd[8];
memset(&cmd, ~0, sizeof(cmd));

cmd[1] &= sugar << 4;
cmd[1] &= milk << 1;
*((UINT16*)(cmd + 3)) = liters;

send(cmd);

原始问题:

我想创建一个 8 字节长的结构.由于原因,我只关心第二个和第三个字节,所有其他字节都必须设置为 0xFF.

Original question:

I want to create an 8 byte long struct. For reasons, I only care about the second and third byte, all other bytes must be set to 0xFF.

它应该是这样的:0xFF [Byte1] [Byte2] 0xFF 0xFF 0xFF 0xFF 0xFF

It should look like this: 0xFF [Byte1] [Byte2] 0xFF 0xFF 0xFF 0xFF 0xFF

我试过这样,但看起来太丑了.

I tried like this, but it seems way too ugly.

struct mystruct
{
    mystruct() : should_be_ff(0xFF), should_also_be_ff(0xFF), sould_be_ff_too(0xFFFFFFFF) {}
    UINT8  should_be_ff;
    UINT16 important_values;
    UINT8  should_also_be_ff;
    UINT32 should_be_ff_too;
 }

我可以使用位域进行填充,但是我无法设置正确的值.

I could use bit fields for filling, but then I'm not able to set the correct values.

我更喜欢这样的:

struct mystruct
{
    0xFF;
    UINT16 important_values;
    0xFFFFFF;
}

有什么想法吗?

我需要这个用于某些专有二进制协议,我无法更改.这只是一个例子,还有更复杂的带有标志和位域的结构.在数组中使用它们会很丑.

I need this for some proprietary binary protocol, which i cannot change. This is just an example, there are more complex structures with flags and bit fields. Using them in an array would be ugly.

我已修改包装以(希望)消除填充错误.

I've modified packing to (hopefully) eliminate padding errors.

推荐答案

我想创建一个 8 字节长的结构体.

I want to create an 8 byte long struct.

您的结构可能不是 8 个字节长.您将在成员之间以及可能在最后进行填充.

Your struct probably isn't 8 bytes long. You'll have padding between members and possibly at the end.

没有标准方法可以保证结构体的大小为 8 个字节.

There is no standard way to guarantee that the size of a struct is 8 bytes.

如果你正好需要 8 个字节,你可以使用一个数组:

If you need exactly 8 bytes, you can use an array:

uint8_t arr[8];                    // exactly 8 bytes
memset(arr, ~0, sizeof arr);       // set all bits to 1 i.e. every byte to 0xff
uint16_t foo = 123u;               // some important 2-byte value
memcpy(arr + 1, &foo, sizeof foo); // copy the 2-byte value to the second and third index

请记住,字节的顺序取决于架构的字节序.

Remember that the order of the bytes depend on the endianness of the architechture.

您当然可以使用这样的结构来表示您自己的应用程序中的协议消息.但是要根据协议发送它,您必须先将其转换为数组.必须逐场进行.由于填充和混叠问题,转换无法跨平台正确执行.我建议使用 char 数组,因为 char 类型有关于别名的特殊规则,使它们更容易使用.

You can certainly use a struct like that to represent the protocol message within your own application. But to send it according to a protocol, you must first convert it to an array. It must be done field-by-field. Casting won't do it correctly across platforms due to padding and aliasing concerns. I recommend using an array of char because char type has special rules regarding aliasing that make them easier to work with.

要将结构实例的未使用位设置为 1,最简单的解决方案可能是 memset:

To set unused bits of your struct instance to 1, the simplest solution is probably memset:

MakeCoffeeCmd object;
memset(&object, ~0, sizeof object);

之后您可以设置使用的字段.然后将每个字段复制到数组中正确的位置.

After that you can set the fields that are used. Then copy each field to their correct slots in the array.

这篇关于用值填充结构体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆