A função void * () é um ponteiro para a função ou uma função retornando um void *?

26

Estou confuso sobre o significado de void *function().
É um ponteiro para a função ou uma função retornando void*? Eu sempre o usei em estruturas de dados como uma função recursiva retornando um ponteiro, mas quando vi um código em multithreading ( pthread), há uma mesma declaração de função. Agora estou confuso qual é a diferença entre eles.

user9515151
fonte
5
A @ goodvibration C foi feita sem formato (e o C ++ "herdou" isso). Even void*function();é sintaticamente correto. Por exemplo, para Python, eles escolheram uma decisão diferente - o formato faz parte da sintaxe. IMHO, os dois lados têm seus prós e contras.
Scheff
3
@goodvibration quanto mais você tentar proteger o programador de fazer o que eles querem mais você começa algo como java;)
idclev 463035818
2
@goodvibration Menos opções, menos flexibilidade. E, por favor, lembre-se de que há décadas atrás eles fizeram isso. É fácil reclamar depois ... ;-)
Scheff
2
Na linguagem C, void *function()é uma função que pega um número arbitrário de argumentos e retorna um valor que, quando desreferenciado, é do tipo nulo . Em C ++, void* function()é uma função que não aceita argumentos e retorna um valor de ponteiro para vazio . Você deve decidir qual idioma está perguntando.
Stephen M. Webb
11
@ StephenM.Webb Você não pode desreferenciar avoid * . Afinal, mesmo se você pudesse, o que você faria com um void?
Fabio diz Reinstate Monica

Respostas:

38

A função tem o tipo de retorno void *.

void *function();

Por isso, sempre prefiro separar o símbolo *do nome da função, como

void * function();

E, como Jarod42indicado em um comentário, você pode reescrever a declaração da função em C ++ usando o tipo de retorno à direita, como

auto function() -> void *;

Se você deseja declarar um ponteiro para funcionar, escreva

void ( *function )();

Ou

void * ( *function )();

Ou um ponteiro para função que retorna o ponteiro para função

void * ( *( *function )() )();
Vlad de Moscou
fonte
2
Por isso, prefiro escrever void* function();. Isso não é tão tentador ... ;-) (A edição aconteceu apenas enquanto escrevia este.)
Scheff
no código que eu declaro void * reader();então em pthread_create(&thread1,null,reader,reader_arg)vez depthread_create(&thread1,null,&reader,reader_arg)
user9515151 22/10/19
11
@ Schaff: Ou mesmo auto function() -> void*(C ++). :)
Jarod42
3
Ou um ponteiro para função que retorna o ponteiro para a função que é o que typedefé para ... ;-)
Andrew Henle
11
@AndrewHenle Com typedef não nos há problema. Um problema surge quando as declarações são usados sem typedef ou uma declaração pseudônimo :).
Vlad de Moscou
7

Sempre que não tenho certeza sobre problemas de sintaxe C, gosto de usar o utilitário cdecl ( versão online ) para interpretar para mim. Ele traduz entre sintaxe C e inglês.

Por exemplo, insiro seu exemplo void *foo()e ele retornou

declare foo como função retornando o ponteiro para anular

Para ver como seria a outra sintaxe, insiro declare foo as pointer to function returning voide ela retornou

vazio (* foo) ()

Isso se torna particularmente útil quando você tem vários níveis de previsões de tipos, estrelas ou colchetes em uma única expressão.

bta
fonte
2

É uma função que retorna um ponteiro para void.

Pense na sua declaração desta maneira:

void *(function());

Esta seria uma função retornando void(ou nada):

void (*function2)();

Pense na declaração acima desta maneira:

void ((*function2)());

Uma maneira muito mais fácil de escrever isso é usar typedefs:

typedef void *function_returning_void_pointer();
typedef void function_returning_nothing();

function_returning_void_pointer function;
function_returning_nothing *function2;

Isso geralmente elimina a confusão em torno dos ponteiros de função e é muito mais fácil de ler.

SS Anne
fonte
0

As declarações em C / C ++ são lidas do identificador para fora após a precedência do operador .

Uma rápida olhada na tabela de precedência do operador C / C ++ na wikipedia revela que o operador de chamada de função ()tem uma precedência mais alta que o operador indireto *. Portanto, suas declarações de função são assim:

  • Comece pelo identificador: functionis

  • function() uma função que não aceita argumentos

  • void* function()e retorna a void*.

Esse princípio geral também se aplica às declarações de array ( []também tem precedência maior que *) e combinações dos dois. assim

int *(*arr[42])();

é lido como

  • arr é
  • arr[42] uma matriz de 42 elementos que são
  • *arr[42] ponteiros para
  • (*arr[42])() funções que não levam argumentos e
  • int *(*arr[42])()retornar um int*.

Demora um pouco para se acostumar com isso, mas depois de entender o princípio, é fácil ler essas declarações sem ambiguidade.

cmaster - restabelece monica
fonte