42

我想添加在编译期间检查结构大小以确保它是预定义大小的代码。例如,当我移植此代码或在编译期间从结构中添加/删除项目时,我想确保此结构的大小为 1024 字节:

#pack(1)
struct mystruct
{
    int item1;
    int item2[100];
    char item3[4];
    char item5;
    char padding[615];
 }

我知道如何在运行时使用如下代码来执行此操作:

 if(sizeof(mystruct) != 1024)
 { 
     throw exception("Size is not correct");
 }

但是如果我在运行时这样做是浪费处理。我需要在编译期间执行此操作。

在编译过程中如何做到这一点?

4

5 回答 5

40

您可以在编译期间检查大小:

static_assert (sizeof(mystruct) == 1024, "Size is not correct");

为此,您需要 C++11。Boost 为 c++11 之前的编译器提供了一种解决方法:

BOOST_STATIC_ASSERT_MSG(sizeof(mystruct) == 1024, "Size is not correct");

请参阅文档

于 2013-10-16T11:19:47.260 回答
23

如果你没有 C++11 或 Boost,你可以试试这个:

typedef char assertion_on_mystruct[(   sizeof(mystruct)==1024   )*2-1 ];

如果该语句为假,则此类型定义为负大小的数组类型,并且您的编译器应给出错误消息。如果为真,则大小将为一,即有效大小。例如,g++ 给出:

template.cpp:10:70: error: size of array ‘assertion_on_mystruct’ is negative

我承认这不是最有用的东西,因为它只告诉你错误的行号。但这是我能想到的最简单、独立的技术。

更通用的宏是:

#define DUMB_STATIC_ASSERT(test) typedef char assertion_on_mystruct[( !!(test) )*2-1 ]

DUMB_STATIC_ASSERT( sizeof(mystruct)==1024 );
DUMB_STATIC_ASSERT( sizeof(my_other_struct)==23 );
DUMB_STATIC_ASSERT( sizeof(minimum_size_struct) >= 23 );
于 2013-10-16T11:28:01.863 回答
6

从 C++11 开始,您可以static_assert在编译时处理:

static_assert(sizeof(mystruct) == 1024, "Size is not correct");

如果大小不是1024字节,则会出现编译错误。

于 2013-10-16T11:19:00.180 回答
4

如果你想在编译时检查它,你可以使用模板元编程阶段。

在标准 C++ 中,您有 boost 的静态断言,它被宏隐藏BOOST_STATIC_ASSERT。您可以通过以下方式使用它:

#include <boost/static_assert.hpp>
...
BOOST_STATIC_ASSERT(sizeof(mystruct) == 1024);

如果不满足断言,上面的代码将无法编译,并带有一些半可读的错误消息。

在 C++11 中,您可以通过引入新关键字的静态断言static_assert获得更简单的功能。

static_assert(sizeof(mystruct) == 1024,"Size is not correct");

无法在预处理器阶段做同样的事情,但在您的情况下似乎并不真正需要。

于 2013-10-16T11:22:47.260 回答
1

请注意,填充包含在 sizeof() 中:

struct A { int i; bool b; };

typedef char assertion_on_A[( ((sizeof(A)))== 8 )*2-1 ];
static_assert(sizeof(A) == 8, "sizeof A");

typedef 和 static_assert 在这里都期望大小为 8。

于 2018-03-02T11:30:55.907 回答