Как вызвать функцию по указателю в C

Я просматривал библиотеку USB Atmel для AT91SAM7, и я кое-что не понимаю. Конечная точка - это структура, определяемая следующим образом:

typedef struct {
    volatile unsigned char  state;
    volatile unsigned char  bank;
    volatile unsigned short size;
    Transfer       transfer;        //thus Endpoint contains an instance of "Transfer"  
} Endpoint

точка; А сама передача представляет собой следующую структуру:

typedef struct {
    char             *pData;
     volatile int     buffered;
    volatile int     transferred;
    volatile int     remaining;
    volatile  TransferCallback  fCallback;
     void             *pArgument;
} Transfer; 

А TransferCallback - это функция со следующим прототипом:

typedef  void  (*TransferCallback)(void *pArg,  unsigned char status, unsigned int transferred, unsigned int remaining);

также два указателя были определены как следующие:

Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);

Я хочу знать, почему такой способ вызова функции TransferCallback действителен:

((TransferCallback) pTransfer->fCallback) (followed by the required arguments passed )

Но это не верно

((TransferCallback)pEndpoint->transfer->fCallback)?

Как я мог напрямую вызвать TransferCallback без использования указателя, такого как pTransfer между ними? Я попробовал несколько комбинаций, но ни одна из них не сработала.

2 ответа

Обратите внимание, что Endpoint нет указателя на элемент Transfer (*Transfer), но член передачи. В терминах машин, а не одно слово памяти в каждом Endpoint используется в качестве указателя на Transfer, все поля Transfer член хранятся непосредственно в памяти, выделенной для Endpoint,

Чтобы перейти к преследованию, вам нужно:

((TransferCallback)pEndpoint->transfer.fCallback)

Относительно заголовка к OP: как вызвать функцию по указателю в C

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

В качестве простого примера, две строковые функции strcat() а также strcpy() есть список аргументов: (char *, const char *)следовательно, может быть назначен массив указателей на функции. Сначала создайте массив указателей на функции:

char * (*pStr[2])( char *a, const char *b);` //array of function pointers pStr[]  

Затем сделайте присвоения strcat и strcpy массиву:

void someFunc(void)
{
    pStr[0] = strcat; //assign strcat to pointer [0]
    pStr[1] = strcpy; //assign strcpy to pointer [1]
}

Сейчас, strcat() или же strcpy() можно назвать как:

int main(void)
{
    char a[100]="kjdhlfjgls";
    char b[100]="kjdhlfjgls";

    someFunc();//define function pointers

    pStr[0](a, "aaaaaaaa");  //strcat
    pStr[1](b, "aaaaaaaa");  //strcpy

    return 0;
}  

Пример вывода:
введите описание изображения здесь

Это всего лишь простой пример. Он не рассматривает всю степень полезности, которую могут предоставить указатели на функции, но иллюстрирует другую причину, по которой указатели на функции могут быть предпочтительнее в некоторых ситуациях.

* Эта иллюстрация нацелена только на C, в отличие от C++, где качества наследования и полиморфизма, присущие этому языку, сделали бы это предложение ненужным.

Другие вопросы по тегам