Reputation: 68426
I am trying to initialize a C struct using the following code:
/* 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"}
};
When I attempt to compile this (gcc 4.6.3), I get the following errors:
error: initializer element is not constant
error: (near initializer for 'fk[0].func_id')
How I can fix this error?
[[Edit]]
After a brief chat with ouah, I have found the reason for this error - it is to do with the function definitions being used to initialize the array. Some of the definition are in different translation units, and others in different modules. All of which means (IIUC) that the functions will not be defined at compile time.
Short of writing an initialization function (which will require extensive mod in existing code) I'm not sure how to solve this - and I'm not sure how it compiled under previous versions of gcc either.
Upvotes: 0
Views: 2382
Reputation: 753695
The function definitions are not material to the problem. The type used for func_id
is, though.
Consider this code:
#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"}
};
As written, using uintptr_t
, this compiles cleanly under GCC 4.8.1 on Mac OS X 10.8.4 (64-bit compilation). Change the type of ptr_t
to int
and you get a pile of warnings. The trouble is that the 64-bit address constants don't fit into a 32-bit int
, so the loader would have to generate code to truncate the addresses, which makes them insufficiently constant. With a 32-bit compilation, the code using int
compiles cleanly too.
So, use a big enough type (uintptr_t
recommended) and you will be OK. The "I know it should be intptr_t
but ignore for now" comment is the source of your trouble; don't ignore it.
Upvotes: 1
Reputation: 145829
typedef _funky {
int func_id; /* I know this should be intptr_t, but ignore for now ... */
char func_name[MAX_FUNC_NAME_LEN];
} Funky;
there is a missing struct
keyword here.
Also:
Funky fk[3] = {
{(int)func1, "func1"}, /* <- gcc barfs here ... */
{(int)func2, "func2"},
{(int)func3, "func3"},
{(int)func4, "func4"}
};
You have 3
elements in your array but you initialize it with 4
initializers.
And as noted in the comments casting a function pointer to a int
is probably a bad idea. There is absolutely no guarantee a function pointer value would fit in an int
object.
Upvotes: 1