5

我有这个编译时出现的错误“致命错误 C1017:无效的整数常量表达式”来自 Visual Studio。我该怎么做?

template <class B>
A *Create()
{
  #if sizeof(B) > sizeof(A)
  #error sizeof(B) > sizeof(A)!
  #endif
  ...
}
4

10 回答 10

16

预处理器不理解 sizeof()(或数据类型、标识符、模板或类定义,它需要理解所有这些东西才能实现 sizeof)。

您正在寻找的是一个静态断言(由编译器强制执行,它确实理解所有这些事情)。我为此使用Boost.StaticAssert :

template <class B>
A *Create()
{
  BOOST_STATIC_ASSERT(sizeof(B) <= sizeof(A));
  ...
}
于 2009-11-11T20:04:16.173 回答
8

在编译器开始编译之前评估预处理器表达式。sizeof() 仅由编译器评估。

于 2009-11-11T20:01:45.600 回答
8

你不能用预处理器做到这一点。预处理器指令不能与诸如sizeof. 此外,即使它们可以,它仍然不起作用,因为很早就从代码中消除了预处理器指令,所以不能期望它们作为稍后实例化的模板代码的一部分工作(这似乎是你想要的达到)。

正确的方法是使用某种形式的静态断言

template <class B>
A *Create()
{
  STATIC_ASSERT(sizeof(B) <= sizeof(A));
  ...
}

那里有很多静态断言的实现。进行搜索并选择最适合您的。

于 2009-11-11T20:03:24.423 回答
6

sizeof() 不能在预处理器指令中使用。

于 2009-11-11T20:00:03.337 回答
6

预处理器在编译器之前运行(至少在逻辑上是这样)并且不了解用户定义的类型(并且不一定对内在类型有太多了解 - 预处理器的 int 大小可能与编译器目标不同。

无论如何,要做你想做的事,你应该使用STATIC_ASSERT(). 请参阅以下答案:

有了 aSTATIC_ASSERT()你就可以做到这一点:

template <class B>
A *Create()
{
    STATIC_ASSERT( sizeof(A) >= sizeof( B));
    return 0;
}
于 2009-11-11T20:06:02.970 回答
3

这不能用预处理器来完成。预处理器在编译器之前执行 - 因此在评估时尚未计算 NodeB 和 Node 的大小#if

您可以使用模板编程技术完成类似的事情。Andrei Alexandrescu 的《Modern C++ Design: Generic Programming and Design Patterns Applied》是一本关于该主题的优秀书籍。

这是一个来自网页的示例,它创建了一个模板 IF 语句。

从该示例中,您可以使用:
IF< sizeof(NodeB)<sizeof(Node), non_existing_type, int>::RET i;

它要么声明一个类型的变量,要么声明一个类型的int变量non_existing_type。假设如果模板 IF 条件评估为真,则不存在的类型符合其名称,将导致编译器错误。您可以重命名i描述性内容。

使用这将是“滚动你自己的”静态断言,其中许多已经可用。我建议您在自己构建一个之后使用其中一个。

于 2009-11-11T20:05:49.287 回答
1

如果您对适用于 C 和 C++ 的编译时断言感兴趣,这是我开发的一个:

#define CONCAT2(x, y)              x ## y
#define CONCAT(x, y)               CONCAT2(x, y)

#define COMPILE_ASSERT(expr, name)     \
    struct CONCAT(name, __LINE__) { char CONCAT(name, __LINE__) [ (expr) ? 1 : -1 ]; }

#define CT_ASSERT(expr)  COMPILE_ASSERT(expr, ct_assert_)

它的工作原理是当表达式为假时数组的大小为负(这是非法的)。通过进一步将其包装在结构定义中,这不会在运行时创建任何内容。

于 2010-05-18T19:23:43.850 回答
0

这已经解释过了,但请允许我详细说明为什么预处理器不能计算结构的大小。除了对简单的预处理器要求太多之外,还有一些编译器标志会影响结构的布局方式。

struct X { short a; long b; };

这个结构可能是 6 字节或 8 字节长,这取决于编译器是否被告知出于性能原因对“b”字段进行 32 位对齐。预处理器不可能有这些信息。

于 2010-05-18T19:12:51.250 回答
0

我看到很多人说 sizeof 不能在预处理器指令中使用,但这不是全部,因为我经常使用以下宏:

#define STATICARRAYSIZE(a) (sizeof(a)/sizeof(*a))

例如:

#include <stdio.h>

#define STATICARRAYSIZE(a) (sizeof(a)/sizeof(*a))

int main(int argc, char*argv[])
{
        unsigned char chars[] = "hello world!";
        double        dubls[] = {1, 2, 3, 4, 5};

        printf("chars num bytes: %ld, num elements: %ld.\n" , sizeof(chars), STATICARRAYSIZE(chars));
        printf("dubls num bytes: %ld, num elements: %ld.\n" , sizeof(dubls), STATICARRAYSIZE(dubls));
}

产量:

orion$ ./a.out 
chars num bytes: 13, num elements: 13.
dubls num bytes: 40, num elements: 5.

然而

我也无法在 gcc 4.2.1 下的 #if 语句中编译 sizeof()。例如,这不会编译:

#if (sizeof(int) == 2)
#error uh oh
#endif

任何见解将不胜感激。

于 2011-04-30T19:29:50.943 回答
0

使用 MSVC,此代码为我编译:

const int cPointerSize = sizeof(void*);
const int cFourBytes = 4;`

#if (cPointerSize == cFourBytes)
    ...

然而这(应该同样工作)不:

#if ( sizeof(void*) == 4 ) ...

于 2011-06-09T06:16:26.703 回答