编译时已知数组大小:通过使用 g++ 的编译但不是 icpc

compile-time-known array size: passed compilation using g++ but not for icpc

玩具代码很简单:

#include <stdio.h>
#include <math.h>

#define A 10
#define SIZE (int)(ceil(A / 2)) // needs computation but known at compile-time

struct node {
    int keys[SIZE];
};

int main() {
    node a_node;
    for (int i = 0; i < SIZE; ++i) {
        a_node.keys[i] = i;
        printf("%d\n", a_node.keys[i]);
    }
    return 0;
}

当我使用 g++ -std=c++11 -O3 test.cpp -o test 编译它时,它按预期通过并运行;但是使用带有 icpc -std=c++11 -O3 test.cpp -o test 的 intel 编译器,出现错误:

test.cpp(8): error: function call must have a constant value in a constant expression int keys[SIZE];

为什么认为是函数调用?但是如果我在宏中使用简单的算术(例如 #define SIZE (A / 2)),错误就会消失。

gcc版本:4.8.5;国际刑事法院版本:16.0.3。

知道如何解决这个问题吗?谢谢。

---------------- 已添加 ------------------

如果 int keys[SIZE] 是在主函数而不是结构中声明的,即像这样:

#include <stdio.h>
#include <math.h>

#define A 10
#define SIZE (int)(ceil(A / 2))

/*struct node {
    int keys[SIZE];
};*/

int main() {
    //node a_node;
    int keys[SIZE];
    for (int i = 0; i < SIZE; ++i) {
        keys[i] = i;
        printf("%d\n", keys[i]);
    }
    return 0;
}

它将通过 gnu 和 intel 编译器。非常有趣和奇怪。我不确定我是否犯了任何我不知道的错误,任何可能的线索?

#define A 10
#define SIZE (int)(ceil(A / 2))

你的 SIZE 而不是 一个 compile-time 常量,因为 ceil<math.h> 的浮点函数。所以编译器将变量 int keys[SIZE]; 理解为语言的 variable length array (VLA) (whose size is probably computed at runtime). Standard C++11 or C++14 don't have VLAs. But GCC accepts them as an extension。请注意,如果您声明 struct node,则 keys 不是变量,而是字段或成员。

顺便说一句,如果将 SIZEdefine 替换为

 #define SIZE ((A+1)/2)

它成为一个 compile-time 常量(例如 C++ 中的 constexpr)并且与以前具有相同的值。

顺便说一句,您的代码不是真正的 C++11,但看起来像 C11 代码。我建议安装更新版本的 GCC (in march 2017, use GCC 6,而不是旧的 4.8)。然后使用 constexprstd::array

VLA 不能作为字段出现在 struct-s 中。 C99 和 C11 有 flexible array members 作为 struct 的可能的 last 成员。 C++11 没有它们。

可能,您的 GCC 编译器(以及 <math.h> header)知道 abs 可以扩展为 __builtin_abs,它由 GCC 编译器专门处理(但是不是其他人)(因此 SIZE 扩展为 (int)(ceil(10 / 2)),特别是 GCC,由于 __builtin_abs 而成为 compile-time 常量)

你应该明白C和C++是不同的语言。如果您选择用 C++ 编写代码(至少 C++11, anything older is obsolete in 2017) you should use its standard containers (and you probably want std::vector since the size is runtime computed). If you choose to code in C (at least C99),请考虑使用灵活的数组成员并在堆中分配您的灵活结构(适当地使用 malloc 或朋友)。请注意,C++ 没有灵活的数组成员。

与您的标题相反,您的 SIZE 而不是 (根据标准规格)一个 "compile-time-known array size"(但通过 gccg++)

使用堆分配的更好理由(即 C++ 中的 std::vector,或指向以灵活数组成员结尾的某些 struct 的指针,或指向数组的指针,在C)是在实践中你会想要一个更大的 A (例如 #define A 100000 ...)并且在 call stack 上分配大数据结构是不合理的(通常在当前的机器和操作系统上限制为一兆或几兆)。