Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 数据类型大小的编译时断言_C++_C_C Preprocessor - Fatal编程技术网

C++ 数据类型大小的编译时断言

C++ 数据类型大小的编译时断言,c++,c,c-preprocessor,C++,C,C Preprocessor,我想对C/C++项目中的数据类型大小执行编译时检查,并对意外的不匹配执行错误检查。简单的 #if sizeof foo_t != sizeof bar_t 不编译-声称sizeof不是正确的编译时常量 平台的期望范围-至少在Visual C++中使用Win32/64,GCC在x86/AMD64 . 编辑:编译时,不一定是预处理器。只是不是一个运行时错误 EDIT2:代码假定wchar\u t为2个字节。如果它是意外地用4字节wchar编译的,我需要一个编译错误。在C++11中,可以使用静态断言

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

#if sizeof foo_t != sizeof bar_t
不编译-声称sizeof不是正确的编译时常量

平台的期望范围-至少在Visual C++中使用Win32/64,GCC在x86/AMD64 .</P> 编辑:编译时,不一定是预处理器。只是不是一个运行时错误


EDIT2:代码假定
wchar\u t
为2个字节。如果它是意外地用4字节wchar编译的,我需要一个编译错误。

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

static_assert(sizeof(foo_t) == sizeof(bar_t), "sizes do not match");
如果是C++11之前的版本,则可以使用boost静态断言宏

您有两个选择:

a) C++11的应用

b) 助推

我更喜欢第一个

编辑:

预处理器并不是该语言的一部分,顾名思义,它预处理文件,它不了解该语言,因此它不知道
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;
模板
X类;
模板
X类{
电视
常量字符*msg()常量{
返回“我的尺码是4”;
}
}
模板
X类{
电视
常量字符*msg()常量{
返回“我的尺码不是4”;
}
}
xA;
xb;

如果您不能使用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>;
然后您将得到一个编译类型错误,但它不是一个非常可读的错误;可能类似于(g++4.4.3):

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


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

您可以定义编译时断言宏,如下所示:

template struct MustBeSameSize<char, int>;
#define COMPILE_TIME_ASSERT( x ) \
  switch ( x ) \
  { \
  case false: \
    break; \
  case ( x ): \
    break; \
  }

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

编译时,编译器无法检测到数据类型大小不匹配或任何常量变量绑定检查,因为编译前会执行预处理器指令。因此,即使可以检测到不匹配,也不能将其作为编译器错误抛出。但是assert()等有助于运行时检测。

PS:我前面给出的答案不适用于普通x86编译器(但适用于ARM编译器)。

编译时断言?或者预处理器时间断言?编译器应该如何在预处理器级别知道复杂结构的大小?如果他们愿意,可能有一些人可以管理它,但它显然超出了
\if
的范围。如果你告诉我们你为什么想要它,那就更好了。因为在这种形式下,你不会得到可以解决这个问题的答案。预处理器无法计算
sizeof
。这只是文本替换的事情。如果一个错误已经足够了,请看一个C和C++有效的解决方案,如果你想做更复杂的处理,我同意马克,PP不能在特殊情况下排除所需的信息。@程序员:负大小数组的窍门听起来最整洁。做个回答,这样我就可以a+1。他要求编译时间,而且预处理器甚至有这些信息吗?@Nawaz,那又怎样?如果大小不匹配,它将给出一个错误,这正是问题所要问的。纳瓦兹:老实说,如何做并不重要,但是预处理器做的越少,标准化语言功能做的越多越好。你确定后一点吗?嗯,Visual C++ 2010没有。至少不在功能级别(即不在结构内部)。@SevaAlekseyev,我不确定我是否理解。您是否确认VC++2010允许结构中使用零长度数组,并且还说它不允许将其作为函数参数?我是说
void f(){char x[0];}
产生编译错误C2466:“无法分配常量大小为0的数组”。感谢您的澄清,@SevaAlekseyev。您可以添加一个“+1”对每个数组大小进行调整,使其能够处理大于字符的所有内容。(假设没有比字符大的奇数基本类型)这似乎完全是胡说八道。GCC 4.9和Visual Studio 2012均未发现任何
#pragma错误
。而且,即使是这样,要使其正常工作,
expr
必须是
constexpr
或在编译时可以确定的,并且不能保证在源代码中编译总是失败的。我怀疑,在实际有
#pragma error
(哪些是?)的编译器中,这并不像您所说的那样。
error: overflow in array dimension
#define COMPILE_TIME_ASSERT( x ) \
  switch ( x ) \
  { \
  case false: \
    break; \
  case ( x ): \
    break; \
  }