我正在尝试使用以下代码初始化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下编译的。
答案 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
但是暂时忽略”评论是你麻烦的根源;不要忽视它。