2013-08-20 4 views
0

Я пытаюсь инициализировать 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') 

Как я могу исправить эту ошибку?

[[Edit]]

После краткой беседы с ouah, я нашел причину этой ошибки - это делать с определением функций, которые используются для инициализации массива. Некоторые из определений находятся в разных единицах перевода, а другие - в разных модулях. Все это означает (IIUC), что функции не будут определены во время компиляции.

Недостаточно написания функции инициализации (которая потребует обширного мод в существующем коде). Я не уверен, как это решить - и я не уверен, как она была скомпилирована в предыдущих версиях gcc.

+1

Это не должно быть intptr_t, это должен быть правильный указатель функции. Зачем игнорировать его, поскольку это, вероятно, ядро ​​вашей проблемы? – Mat

+0

@Mat: Это поле в структуре также используется для хранения целых чисел в частях кода. Я работаю с устаревшим кодом, и эта структура используется в более чем 5k файлах - иногда в поле хранится int, а в других случаях он содержит необработанный ptr. Лучшее, что я могу сделать, это изменить его на intptr_t, это потребует наименьшей модификации для тела существующего кода. –

+1

«intptr_t' не гарантированно может удерживать значение указателя функции без потери информации, хотя, вероятно, это возможно. (Вероятно, 'uintptr_t' будет иметь немного больше смысла, чем' intptr_t'.) –

ответ

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, это компилируется под GCC 4.8.1 на Mac OS X 10.8.4 (64-разрядная версия компиляции). Измените тип ptr_t на int, и вы получите кучу предупреждений. Проблема в том, что 64-разрядные константы адреса не вписываются в 32-разрядный int, поэтому загрузчик должен будет генерировать код для усечения адресов, что делает их недостаточно постоянными. С 32-разрядной компиляцией код с использованием int компилируется также чисто.

Итак, используйте достаточно большой тип (uintptr_t), и все будет в порядке. «Я знаю, что это должно быть intptr_t, но игнорировать пока» комментарий - источник вашей проблемы; не игнорируйте его.

+0

+1 для хонингования прямо по проблеме и для подробное объяснение. –

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.

+0

Мой плохой, я исправлю код, который я представил. Это не причина проблемы, которую я испытываю, хотя –

+0

@HomunculusReticulli вы видели последнее редактирование? Я думаю, что это причина вашего сообщения об ошибке. – ouah

+0

@HomunculusReticulli ok, другое редактирование на ваш исходный вопрос. Вы уверены, что макрос 'MAX_FUNC_NAME_LEN' определен в вашей программе, попробуйте использовать некоторое фиксированное значение, например' 256' для тестирования. Кроме того, пожалуйста, используйте некоторые правильные примеры в ваших вопросах. – ouah

Смежные вопросы