Размер массива указателей на функцию

297
19 января 2017, 04:26

Не могу разобраться как найти размер массива указателей на функцию.

int show(void(*f[])(int _x))
{
    return sizeof((*f[])(0)) / sizeof((*f)(0))); 
}
Answer 1

Для такого объявления функции

int show(void(*f[])(int _x))
{
    return sizeof((*f[])(0)) / sizeof((*f)(0))); 
} 

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

Поэтому объявление функции выглядит следующим образом

int show(void(**f)(int _x))
{
    return sizeof((*f[])(0)) / sizeof((*f)(0))); 
} 

То есть параметр функции - это указатель на указатель функции.

У тому же выражение в теле функции в любом случае некорректное.

В C вам следует также передавать в функцию размер массива. В C++ вы могли бы объявить параметр как ссылку на массив.

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

#include <iostream>
void f(int) { std::cout << "f" << std::endl; }
void g(int) { std::cout << "g" << std::endl; }
int h(void(**fp)(int), size_t n )
{
    for ( size_t i = 0; i < n; i++ ) fp[i]( 0 );
    return 0;
}
template <size_t N>
int h( void ( *( &fp )[N] )( int ) )
{
    for (size_t i = 0; i < N; i++) fp[i](0);
    return 0;
}
/*
using FP = void ( * )( int );
template <size_t N>
int h( FP ( &fp)[N] )
{
    for (size_t i = 0; i < N; i++) fp[i](0);
    return 0;
}
*/
int main()
{
    void ( *fp[] )( int ) = 
    {
        f, g
    };
    h(fp, sizeof( fp ) / sizeof( *fp ) );
    h(fp);
    return 0;
}

Вывод программы на консоль

f
g
f
g

Закомментированный код показывает, как можно использовать using объявление, чтобы объявление ссылочного шаблонного параметра функции было проще.

Как видно из программы, если объявить параметр как ссылку на массив, то получить размер массива аргумента не составляет труда. Он равен шаблонному параметру N.

Вот демонстрационная программа на C.

#include <stdio.h>
void f(int x ) { printf( "f(%d)\n", x  ); }
void g(int x ) { printf( "g(%d)\n", x  ); }
int h(void(**fp)(int), size_t n )
{
    for ( size_t i = 0; i < n; i++ ) fp[i]( i );
    return 0;
}

int main(void) 
{
    void ( *fp[] )( int ) = 
    {
        f, g
    };
    h(fp, sizeof( fp ) / sizeof( *fp ) );
    return 0;
}
Answer 2

В данном случае - никак.

Вы же в функции, куда передается адрес начала массива. Сведения о его размере остались в месте его определения (там где отводили под него память).

Вот там sizeof(f) / sizeof(f[0]) работает и это выражение можно запомнить и передать в функцию вместе с массивом.

Как-то так

void
do_it (int (*f[])(), size_t asize)
{
  printf("array %zd items\n", asize);
}
int
main (int ac, char *av[])
{
  int (*f[])() = {f1, f2, f3};
  printf("%ld\n", sizeof(f) / sizeof(f[0]));
  do_it(f, sizeof(f) / sizeof(f[0]));
}
READ ALSO
Поддержка html + css + javascript интерфейсов

Поддержка html + css + javascript интерфейсов

Существуют ли фреймоврки под C++ язык, которые позволяют использовать HTML + Javascript UI интерфейсы в своих проектах?

280
Пустой экран при запуске вместо окошка с вводом текста и клавиатуры - класс Text(С++, Cocos2d-x)

Пустой экран при запуске вместо окошка с вводом текста и клавиатуры - класс Text(С++, Cocos2d-x)

Добрый вечер!Я работаю в visual studio 2015, используя cocos2d-xУ меня возникла странная проблема

317
Рациональность использования QTabWidget [требует правки]

Рациональность использования QTabWidget [требует правки]

Рационально ли использовать QTabWidget для переключения и показа открытых файлов (как показано на картинке слева)? Есть ли более оптимальный способ?

233
Как проверить была ли нажата любая клавиша на клавиатуре?

Как проверить была ли нажата любая клавиша на клавиатуре?

Задача состоит в том, что бы в цикле проверить, была ли нажата во время выполнения цикла какая либо клавиша на клавиатуре, и если была нажата...

262