编译时已知数组大小:通过使用 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
不是变量,而是字段或成员。
顺便说一句,如果将 SIZE
的 define
替换为
#define SIZE ((A+1)/2)
它成为一个 compile-time 常量(例如 C++ 中的 constexpr
)并且与以前具有相同的值。
顺便说一句,您的代码不是真正的 C++11,但看起来像 C11 代码。我建议安装更新版本的 GCC (in march 2017, use GCC 6,而不是旧的 4.8)。然后使用 constexpr
和 std::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"(但通过 gcc
或 g++
)
使用堆分配的更好理由(即 C++ 中的 std::vector
,或指向以灵活数组成员结尾的某些 struct
的指针,或指向数组的指针,在C)是在实践中你会想要一个更大的 A
(例如 #define A 100000
...)并且在 call stack 上分配大数据结构是不合理的(通常在当前的机器和操作系统上限制为一兆或几兆)。
玩具代码很简单:
#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
不是变量,而是字段或成员。
顺便说一句,如果将 SIZE
的 define
替换为
#define SIZE ((A+1)/2)
它成为一个 compile-time 常量(例如 C++ 中的 constexpr
)并且与以前具有相同的值。
顺便说一句,您的代码不是真正的 C++11,但看起来像 C11 代码。我建议安装更新版本的 GCC (in march 2017, use GCC 6,而不是旧的 4.8)。然后使用 constexpr
和 std::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"(但通过 gcc
或 g++
)
使用堆分配的更好理由(即 C++ 中的 std::vector
,或指向以灵活数组成员结尾的某些 struct
的指针,或指向数组的指针,在C)是在实践中你会想要一个更大的 A
(例如 #define A 100000
...)并且在 call stack 上分配大数据结构是不合理的(通常在当前的机器和操作系统上限制为一兆或几兆)。