我必须通过包装部分未按字节对齐的网络发送一些数据。所有程序包的长度均为8字节,示例程序包类型可能如下所示:
union Packed
{
struct
{
uint64_t a : 5;
uint64_t b : 10;
bool c : 1;
};
uint64_t raw;
};
因此,前5位是字段a
,接下来的10位是字段b
,最后一位是字段c
。现在,我需要一个send
函数,可以发送此包类型以及其他包类型。该函数应接受字段作为参数。低级发送功能接受单个uint64_t
。
编辑 如注释中所指出,在写入raw
,a
或{{ 1}}。明确地说:这也是我要更改的内容,但我将其包含在顶部,因为所有尝试都使用了联合。
我的要求是:
b
生成的警告满足我的第一个要求,但是我不喜欢语法:花括号看起来多余,而首先手动创建结构很麻烦。
启用一些警告后,我什至必须使用两层花括号,因为该结构嵌套在联合中。
c
在这里,我喜欢语法,但不会生成警告,大概是因为位宽在某处丢失了。
void send_struct(const Packed& packed)
{
raw_send(packed.raw);
}
int main()
{
send_struct({1000, 2, true}); // conversion changes value
Packed packed = {1000, 2, true}; // conversion changes value
send_struct(packed);
}
第一种用法又很丑:花括号太多,第二种不能编译,因为不能用单个值隐式构造这些结构。
我如何实现函数和安全的包定义,以使以下函数调用编译并 显示警告,因为值template <typename ...Args>
void send_var(Args... args)
{
Packed packed {args...};
raw_send(packed.raw);
};
int main()
{
send_var(1000u, 2u, true);
}
不适合5位。
struct A
{
uint64_t data : 5;
};
struct B
{
uint64_t data : 10;
};
void send_separate(A a, B b, bool c)
{
Packed packed {a.data, b.data, c};
raw_send(packed.raw);
}
int main()
{
send_separate({1000u}, {2u}, true); // conversion changes value
send_separate(1000u, 2u, true); // compile error
}
我实际上只关心呼叫站点。函数和联合定义可能会更复杂。
编辑2
使用变量作为参数必须 也应。
1000
该软件将仅在Linux上使用,并使用send(1000u, 2u, true);
或uint64_t a, b;
send(a, b, true); // compiles, but may generate a warning
send(a & 0x1f, b & 0x3ff, true); // compiles preferably without a warning
进行编译,并至少使用以下警告:gcc
以及允许匿名结构和联合的标志。