初始化结构数组(编译器错误:初始化元素不是常量)

时间:2013-08-20 22:03:47

标签: c gcc compiler-errors

我正在尝试使用以下代码初始化C结构:

/* header file */

typedef struct _funky {
   int  func_id;  /* I know this should be intptr_t, but ignore for now ... */
   char func_name[MAX_FUNC_NAME_LEN];
} Funky;


double func1(double d1, double d2, double d3);
double func2(double d1, double d2, double d3);
double func3(double d1, double d2, double d3);
double func4(double d1, double d2, double d3);


/* .c file */
Funky fk[4] = {
                 {(int)func1, "func1"}, /* <- gcc barfs here ... */
                 {(int)func2, "func2"},
                 {(int)func3, "func3"},
                 {(int)func4, "func4"}
              };

当我尝试编译它(gcc 4.6.3)时,我收到以下错误:

error: initializer element is not constant
error: (near initializer for 'fk[0].func_id')

我如何解决此错误?

[[编辑]]

在与ouah进行简短的聊天后,我发现了这个错误的原因 - 它与用于初始化数组的函数定义有关。一些定义在不同的翻译单元中,而其他定义在不同的模块中。所有这些意味着(IIUC)在编译时不会定义函数。

没有编写初始化函数(在现有代码中需要大量的mod)我不知道如何解决这个问题 - 我不确定它是如何在以前版本的gcc下编译的。

2 个答案:

答案 0 :(得分:1)

typedef _funky {
   int  func_id;  /* I know this should be intptr_t, but ignore for now ... */
   char func_name[MAX_FUNC_NAME_LEN];
} Funky;

此处缺少struct个关键字。

此外:

Funky fk[3] = {
                 {(int)func1, "func1"}, /* <- gcc barfs here ... */
                 {(int)func2, "func2"},
                 {(int)func3, "func3"},
                 {(int)func4, "func4"}
              };

您的数组中有3个元素,但您使用4初始值设定项初始化它。

正如评论中所指出的那样,向int投射一个函数指针可能是一个坏主意。绝对不能保证函数指针值适合int对象。

答案 1 :(得分:1)

函数定义对问题不重要。但是func_id使用的类型是。

考虑以下代码:

#include <stdint.h>
#define MAX_FUNC_NAME_LEN  6

typedef uintptr_t ptr_t;

typedef struct Funky
{
   ptr_t  func_id;  /* I know this should be intptr_t, but ignore for now ... */
   char func_name[MAX_FUNC_NAME_LEN];
} Funky;

double func1(double d1, double d2, double d3);
double func2(double d1, double d2, double d3);
double func3(double d1, double d2, double d3);
double func4(double d1, double d2, double d3);

Funky fk[4] = {
                 {(ptr_t)func1, "func1"}, /* <- gcc barfs here ... */
                 {(ptr_t)func2, "func2"},
                 {(ptr_t)func3, "func3"},
                 {(ptr_t)func4, "func4"}
              };

正如所写,使用uintptr_t,这在Mac OS X 10.8.4(64位编译)下在GCC 4.8.1下完全编译。将ptr_t的类型更改为int,您会收到一堆警告。问题是64位地址常量不适合32位int,因此加载器必须生成代码来截断地址,这使得它们不够恒定。使用32位编译时,使用int的代码也可以完全编译。

所以,使用足够大的类型(推荐uintptr_t),你就可以了。 “我知道它应该是intptr_t但是暂时忽略”评论是你麻烦的根源;不要忽视它。