c - инициализировать массив указателей на функции

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

Это то, что я пытался до сих пор, но я получаю синтаксическую ошибку:

int (*func)() fparr[5] = int (*func)();

Что не так с этим синтаксисом?

4
Почему вы выполняете = int (* func) (); ?
добавлено автор Masked Man, источник

8 ответы

Если функция, которую вы хотите предоставить в качестве содержимого по умолчанию в массиве, называется func , тогда

  1. вам лучше использовать typedef ,
  2. вам нужно использовать инициализатор массива

Рассматривать:

typedef int (*IntFunc)(void);
IntFunc fparr[5] = { func, func, func, func, func };

Или менее читаемый способ, если вы предпочитаете избегать typedef :

int (*fparr[5])(void) = { func, func, func, func, func };
12
добавлено
Неверный путь typedef . Он должен быть int (* fparr [5]) (void) = ... . Это не только менее читаемо, но и менее доступно для записи.
добавлено автор Daniel Fischer, источник
Это несчастье, чтобы понять это неправильно, взгляните на всех остальных на этой странице;)
добавлено автор Daniel Fischer, источник
Потому что, несмотря на то, что 18 (согласно вашему профилю, если это не изменилось в последние дни), вы в основном здравомыслящие.
добавлено автор Daniel Fischer, источник
@DanielFischer Право. Как, возможно, я могу ошибаться?
добавлено автор user529758, источник
@DanielFischer Sure ... :) (Почему, по-твоему, я предположил, что typedef ...)
добавлено автор user529758, источник
@DanielFischer (Нет, это изменилось 28 июня в последний раз) - ну, по крайней мере, я стараюсь больше не запутывать вещи. Но иногда я это делаю.
добавлено автор user529758, источник

Поскольку вы на самом деле не инициализируете массив указателей функций ... попробуйте:

int (*fparr[5])(void) = { func1, func2, func3, func4, func5 };
3
добавлено

Шаг 1:

определить подпись функций как тип FN :

typedef int (*FN)();

<Сильный> Шаг 2:

определить 5 функций с помощью FN :

int f1(void) { ; }
int f2(void) { ; }
...

Шаг 3:

определить и инициализировать массив из 5 функций типа FN :

FN fparr[5] = {f1,f2,f3,f4,f5}

otherwise:

Если вы не хотите определять отдельную подпись, вы можете сделать это - как сказано ранее - так:

 int ((*)fpar [])() = {f1,f2, ...}

Если вы знаете количество функций из массива в момент объявления, вам не нужно писать 5 , компилятор выделил вам эту память, если вы инициализируете массив в той же строке, что и декларация.

2
добавлено
если вы используете typedef int (* FN) (); вместо typedef int (* FN) (void); компилятор с радостью примет static int can_has_arg ( int x) {return x; } FN fparr [] = {can_has_arg} , в то время как Том заявил, что ему нужен массив указателей на функции без аргументов
добавлено автор Christoph, источник
@Christoph: В стандарте C, f() и f (void) разные. () сообщает компилятору отключить проверку параметров. например, если вы хотите добавить 1 к переменной i перед вызовом функции f, вы можете сделать это так: int f() {;} main() {int i = 3 ; F (я ++); е ( "% d", я);} .
добавлено автор alinsoar, источник

Ну, я опаздываю ...

#include 

int fun0()
{
    return 0;
}

int fun1()
{
    return 1;
}

int fun2()
{
    return 2;
}

int main(int argc, char* argv[])
{
    int (*f[]) (void) = {fun0, fun1, fun2};
    printf("%d\n", f[0]());
    printf("%d\n", f[1]());
    printf("%d\n", f[2]());
    return 0;
}
1
добавлено
ПОСТОЯННЫЕ ПАРАМЕТРЫ НЕ ЭКВИВАЛЕНТЫ, КОТОРЫЕ НАРУШАЮТСЯ В C (gcc -Wstrict-prototypes предупреждает: Объявление функции не является прототипом
добавлено автор Jens, источник
лучше поздно, чем никогда !
добавлено автор alinsoar, источник
@Jens Спасибо за комментарий. Я починю это.
добавлено автор bwdeng, источник

Я просто добавлю немного больше к приведенным выше ответам. Массив указателей функций может быть проиндексирован переменной перечисления, отображающей тип операции для каждого индекса. Взгляните на следующий пример. Здесь мы используем tyepdef для оператора указателя функций. Затем мы создаем массив этого указателя функции, называемого act. Наконец, мы инициализируем массив функциями инкремента и декремента. В этом случае индекс 0 относится к приращению, а индекс 1 относится к декременту. Вместо использования этого необработанного индексирования мы используем перечисление с INCR и DECR, соответствующее индексу 0, 1.

#include
#include

typedef void (*operate)(int *, int);
void increment(int *, int);
void decrement(int *, int);

enum {
   INCR, DECR
    };

 int main(void){

   int a = 5;

  operate act[2] = {increment,decrement};

  act[INCR](&a,1);

  printf("%d\n",a);

  act[DECR](&a,2);

  printf("%d\n",a);
     return 0;
 }

 void increment(int *a, int c){
 *a += c;
 }
 void decrement(int *a, int c){
 *a -= c;
  }
1
добавлено

Вот рабочий пример, показывающий правильный синтаксис:

#include 

int test1(void) {
    printf("test1\n");
    return 1;
}

int test2(void) {
    printf("test2\n");
    return 2;
}

int main(int argc, char **argv) {
    int (*fparr[2])(void) = { test1, test2 };

    fparr[0]();
    fparr[1]();

    return 0;
}
0
добавлено
test1 и test2: управление достигает конца не-void функции. И пустые списки параметров должны быть записаны (void) not () , потому что последний является старым (K & R C) и C99-устаревшим.
добавлено автор Jens, источник
Благодарю. Я обновил этот пример.
добавлено автор Sean Bright, источник

Пример кода:

static int foo(void) { return 42; }

int (*bar[5])(void) = { foo, foo, foo, foo, foo };

Обратите внимание, что типы int (*)() и int (*) (void) - это разные типы: первая обозначает функцию с фиксированным, но неопределенным числом аргументов, тогда как последняя обозначает функцию без аргументов.

Также обратите внимание, что синтаксис C-декларатора следует тем же правилам, что и выражения (в частности, приоритет оператора) и, таким образом, считывается наизнанку:

bar denotes and array (bar[5]) of pointers (*bar[5]) to functions (int (*bar[5])(void)). The parens (*bar[5]) are necessary because postfix function calls bind more tightly than prefix pointer indirection.

0
добавлено

Массив указателей на функции может быть инициализирован другим способом со значением по умолчанию.


Пример кода

<div class="snippet" data-lang="js" data-hide="false"> <div class="snippet-code">

   
#include 

void Добавить(int index, int a, int b){
    printf("%d. %d + %d = %d\n", index, a, b, a + b);
}
void суб(int index, int a, int b){
    printf("%d. %d - %d = %d\n", index, a, b, a - b);
}
int main(){
    void (*func[10])(int, int, int) = {[0 ... 9] = Добавить};
    func[4] = суб;
    int i;
    for(i = 0; i < 10; i++)func[i](i, i + 10, i + 2);
}
   
</div> </div> If you run the above program, you will have the below Вывод. All elements are initialized with function Добавить, but 4th element in array is assigned to function суб


Вывод

<div class="snippet" data-lang="js" data-hide="false"> <div class="snippet-code">

0. 10 + 2 = 12
1. 11 + 3 = 14
2. 12 + 4 = 16
3. 13 + 5 = 18
4. 14 - 6 = 8
5. 15 + 7 = 22
6. 16 + 8 = 24
7. 17 + 9 = 26
8. 18 + 10 = 28
9. 19 + 11 = 30
</div> </div>

0
добавлено