В каких ситуациях мы должны использовать функцию signature void * (*) ()? - PullRequest
0 голосов
/ 30 июля 2011

Этот вопрос возникает у меня в голове, когда я смотрю на синопсис pthread_create, а именно:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);

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

void (*start_routine)(void *)

или даже

void (start_routine)(void *)

В общем, в каких ситуациях мы должны использовать сигнатуру функции, подобную третьему параметру, приведенному выше?

Ответы [ 3 ]

3 голосов
/ 30 июля 2011

Синтаксис указателя на функцию C общеизвестно уродлив и труден для понимания.По сути, ответ заключается в том, что так должно быть, потому что так решили разработчики языка C.

void *(*start_routine) (void *) ссылается на указатель на функцию, принимающую один параметр типа void *, ивозвращение void *.

Первый приведенный вами пример void (*start_routine)(void *) также является указателем функции и также принимает параметр void *, но ничего не возвращает.

Другой пример,void (start_routine)(void *) не является указателем на функцию и ничего не возвращает.Круглые скобки на самом деле не служат какой-либо цели, и это было бы то же самое, что написать void start_routine(void *), который, я уверен, не допускается в качестве типа параметра.

Редактировать: этот фактически разрешен какпараметр, но он не так широко используется и все еще имеет неправильный тип возврата.

Надеюсь, что все прояснится.

2 голосов
/ 30 июля 2011

Давайте посмотрим, что cdecl может сказать об этом:

объявить start_routine как указатель на функцию (указатель на void), возвращающий указатель на void

Первый void * означает, что функция возвращает общий указатель. (*start_routine) означает, что параметр является указателем (на функцию). (void *) означает, что функция принимает один аргумент, общий указатель.

0 голосов
/ 30 июля 2011

Start_routine принимает void*, чтобы позволить стартеру потока передать некоторые произвольные данные новому потоку. Он возвращает void*, чтобы поток мог возвращать вызывающему код значимый код завершения (вместо явного вызова pthread_exit из функции потока).

Обратите внимание, что ваше второе предложение (void (start_routine)(void*) не является указателем функции, и поэтому не является опцией для параметра pthread_create или любой другой функции вообще.

...