编译时断言数据类型大小

时间:2011-12-05 16:23:44

标签: c++ c c-preprocessor

我想对C / C ++项目中的数据类型大小执行编译时检查,并在意外不匹配时执行错误。简单

#if sizeof foo_t != sizeof bar_t

不编译 - 声称sizeof不是正确的编译时常量。

所需的平台范围 - 至少使用Win32 / 64的Visual C ++和x86 / amd64上的GCC。

编辑:编译时,不一定是预处理器。只是不是运行时错误。

EDIT2 :代码假定wchar_t为2个字节。如果用4字节的wchar意外编译,我想要编译错误。

5 个答案:

答案 0 :(得分:10)

在C ++ 11中,您可以使用静态断言

static_assert(sizeof(foo_t) == sizeof(bar_t), "sizes do not match");

如果它是C ++之前的11,那么你可以使用boost static assert macro

http://www.boost.org/doc/libs/1_48_0/doc/html/boost_staticassert.html

BOOST_STATIC_ASSERT(sizeof(int)==sizeof(unsigned));
BOOST_STATIC_ASSERT_MSG(sizeof(int)==sizeof(unsigned), "sizes do not match");

答案 1 :(得分:5)

您有两种选择:

a)C ++ 11的static_assert

b)BOOST_STATIC_ASSERT的提升

我更喜欢第一个。

修改

预处理器实际上并不是语言的一部分,因为名称表示它预处理文件,它不知道语言,所以它不知道sizeof

您可以使用一些模板来编译代码,例如:

template <typename T, bool x = sizeof(T) == 4>
class X;

template <typename T>
class X<T, true> {
  T v;
  const char* msg() const {
    return "My size is 4";
  }
}

template <typename T>
class X<T, false> {
  T v;
  const char* msg() const {
    return "My size is NOT 4";
  }
}

X<int> a;
X<short> b;

答案 2 :(得分:3)

如果您不能使用C ++ 11或Boost,那么您可能会觉得这很有用:

template <typename A, typename B>
struct MustBeSameSize {
    int c[sizeof(A)-sizeof(B)];
    int d[sizeof(B)-sizeof(A)];
};
template struct MustBeSameSize<int, int>;

只有当sizeof两种类型相同时才会编译。如果他们是这样的:

template struct MustBeSameSize<char, int>;

然后你会得到一个编译类型的错误,但它不会是一个非常可读的错误;也许像(g ++ 4.4.3):

error: overflow in array dimension

这是有效的,因为任何现代编译器都应该允许零长度数组,但不允许负长度数组。

这对我有用,我认为G ++已经允许零长度数组一段时间了。但我不确定这是多么便携。 C99允许灵活的阵列成员(即未指定的大小),但我不认为这是直接相关的。简而言之,如果您需要可移植的东西,请使用C ++ 11或使用Boost。

答案 3 :(得分:3)

您可以像这样定义编译时断言宏:

#define COMPILE_TIME_ASSERT( x ) \
  switch ( x ) \
  { \
  case false: \
    break; \
  case ( x ): \
    break; \
  }

如果表达式为false,则会出现重复的大小写标签错误。

答案 4 :(得分:-3)

在编译时,编译器无法通过编译器找到数据类型大小不匹配或任何const变量绑定检查,因为在编译之前会对处理器前指令执行操作。因此,即使您可以检测到不匹配,也无法将其作为编译器错误抛出。但是assert()等可以帮助运行时检测 PS:我之前给出的答案与普通的x86编译器无关(但与ARM编译器一起使用)。