0
点赞
收藏
分享

微信扫一扫

[c++实践]利用static_assert进行编译期错误检查

需求产生的背景

在开发某通信应用时,由于某些原因,需要将接收的结构体A转换成另外一结构体B进行使用,其实它们是完全等价的。但在开发的过程中,由于AB并不是来自于同一头文件,因此会存在潜在的结构体不一致的情况。为了避免这种潜在的错误导致的运行时错误,我们在收到结构体A的时候比较了AB的大小,至少保证其大小一致,在进行内存操作时是安全的,其代码大致如下:

void onRecvData(const struct DataA *data)
{
    if (sizeof(DataA) != sizeof(DataB)
    {
        std::cout << "size not match..." std::endl;
        return;
    }
    struct DataB dst;
    memcpy(&dst,data,sizeof(DataA));
    // do something else
}

上面的代码运行的很好,没啥问题。在某次发布软件后,测试返回好几个测试用例都失败了,于是一个个的排查,看到的日志是"size not match..."。嗯,原来是输入的结构体struct DataA没有按照文档进行设计导致的。

上面这种情况,我们只能在发布软件之前自己运行测试程序,然后过滤日志,排查是否存在大小不匹配的情况。作为一个开发人员,当然不愿意手动执行这些操作了,那么该如何解决呢?答案就是static_assert

static_assert 介绍

static_assert很简单,它和assert的唯一区别就是前者是进行编译期的静态检查,不存在运行时开销,如果断言失败会导致编译失败;后者是运行时判断,如果断言失败会导致程序被kill掉。static_assert原型如下:

// 在con为false的时候,将输出exp错误信息,并且导致编译无法通过
static_assert(con,exp)

利用static_assert进行编译期错误检查

struct DataA
{
    int32_t a;
    char c;
    int64_t d;
}

struct DataB
{
    int32_t a;
    int64_t d;
} 

struct DataC
{
    int32_t a;
    int64_t d;
} 

void static_assert_test()
{
    // 本行将导致编译失败,因为这两个结构体大小不一致
    static_assert(sizeof(struct DataA) == sizeof(struct DataB),"DataA and DataB size not match...");

    // 编译OK
    static_assert(sizeof(struct DataC) == sizeof(struct DataB),"DataC and DataB size not match...");
}
举报

相关推荐

0 条评论