Как мне включить разные типы в массив структур?

#c #function-pointers

#c #указатели на функции

Вопрос:

Я пишу программу, которая использует таблицу поиска для вызова функции или возврата константы на основе совпадения с ее именем. Каждый элемент в таблице определяется структурой tbl_entry_t:

 typedef int (*fn_ptr_type)(int);

typedef struct {
  char *str;
  union {
    fn_ptr_type fptr;
    int number;
  };
} tbl_entry_t;
 

Например, вот пример небольшой таблицы:

 int squareFun (int x) { return x * x; }
int cubeFun (int x) { return x * x * x; }
int Hundred = 100;

char string0[] = "square";
char string1[] = "cube";
char string2[] = "hundred";

tbl_entry_t lookup_table[] = {
  { string0, squareFun },
  { string1, cubeFun },
  { string2, Hundred }
};
 

Я хочу смешать значения fn_ptr_type и int в таблице, и я включил объединение в структуру, чтобы попытаться достичь этого, но я все равно получаю предупреждение компилятора:

 { string2, Hundred }
warning: invalid conversion from 'int' to 'fn_ptr_type {aka int (*)(int)}'
 

Как правильно это сделать?

Комментарии:

1. как это связано с C ? это классический C вопрос. исправлены теги

2. { string2, Hundred } Итак, откуда вы знаете, что вы должны использовать number вместо fptr ? Эта таблица поиска имеет для меня мало смысла.

3. «как это связано с C » Тем фактом, что для лучшего ответа может потребоваться C ?

Ответ №1:

Вам нужно указать элемент объединения, который вы хотите инициализировать — в противном случае по умолчанию инициализируется первый элемент:

 tbl_entry_t lookup_table[] = {
  { string0, squareFun },
  { string1, cubeFun },
  { string2, .number = Hundred }  // like this
};
 

например, в реальном времени: https://godbolt.org/z/9WobrG

Ответ №2:

ответ @code_fodder — это то, что я искал, но, к сожалению, в моем компиляторе GCC это выдает ошибку:

   { string2, .number = Hundred }
sorry, unimplemented: non-trivial designated initializers not supported
 

Однако я нашел уродливое решение, которое принимается и позволяет избежать предупреждения, которое заключается в записи:

 tbl_entry_t lookup_table[] = {
  { string0, squareFun },
  { string1, cubeFun },
  { string2, (fn_ptr_type)Hundred }  // workaround
};
 

Комментарии:

1. non-trivial designated initializers not supported Скомпилируйте свой код с помощью компилятора C, а не с помощью компилятора C .

2. Какую версию GCC вы используете? — Я предполагаю, что он довольно старый?

3. похоже, это работает с gcc (c-compilation) начиная с версии 8.1 и далее: godbolt.org/z/so8PWK

4. Я использую avr-gcc версии 7.3.0.

5. @johnsondavies …. ах, если бы вы обновили одну версию до 8.1, вам не пришлось бы использовать свой ужасный хак — но, если это сработает … 🙂