从函数参数填充位域结构的简洁语法

时间:2019-02-27 11:01:05

标签: c++ c++11 bit-fields

我必须通过包装部分未按字节对齐的网络发送一些数据。所有程序包的长度均为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

编辑 如注释中所指出,在写入rawa或{{ 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以及允许匿名结构和联合的标志。

0 个答案:

没有答案