La fonction void * function () est-elle un pointeur sur la fonction ou une fonction renvoyant un void *?

26

Je suis confus quant à la signification de void *function().
Est-ce un pointeur pour fonctionner ou une fonction qui revient void*? Je l'ai toujours utilisé sur les structures de données comme une fonction récursive renvoyant un pointeur, mais quand j'ai vu un code dans multithreading ( pthread) il y a la même déclaration de fonction. Maintenant, je ne sais pas quelle est la différence entre eux.

user9515151
la source
5
@goodvibration C a été rendu sans format (et C ++ a "hérité" de cela). Même void*function();est syntaxiquement correct. Par exemple, pour Python, ils ont choisi une décision différente - le format fait partie de la syntaxe. À mon humble avis, les deux façons ont leur pour et leur contre.
Scheff
3
@goodvibration plus vous essayez de protéger le programmeur de ce qu'il veut, plus vous obtenez quelque chose comme java;)
idclev 463035818
2
@goodvibration Moins d'options, moins de flexibilité. Et, s'il vous plaît, gardez à l'esprit qu'il y a des décennies, ils l'ont fait. Il est facile de se plaindre par la suite ... ;-)
Scheff
2
Dans le langage C, void *function()est une fonction prenant un nombre arbitraire d'arguments et renvoyant une valeur qui, lorsqu'elle est déréférencée, est de type void . En C ++, void* function()est une fonction ne prenant aucun argument et renvoyant une valeur de pointer-to-void . Vous devez vous décider sur la langue que vous demandez.
Stephen M. Webb
1
@ StephenM.Webb Vous ne pouvez pas déréférencer avoid * . Après tout, même si vous le pouviez, que feriez-vous avec un void?
Fabio dit Réintégrer Monica

Réponses:

38

La fonction a le type de retour void *.

void *function();

Donc je préfère toujours dans de tels cas séparer le symbole *du nom de la fonction comme

void * function();

Et comme Jarod42indiqué dans un commentaire, vous pouvez réécrire la déclaration de fonction en C ++ en utilisant le type de retour de fin comme

auto function() -> void *;

Si vous voulez déclarer un pointeur pour fonctionner, vous devez écrire

void ( *function )();

Ou

void * ( *function )();

Ou un pointeur sur la fonction qui renvoie le pointeur sur la fonction

void * ( *( *function )() )();
Vlad de Moscou
la source
2
C'est pourquoi, je préfère écrire void* function();. Ce n'est pas si tentant ... ;-) (L'édition s'est produite juste en écrivant ceci.)
Scheff
dans le code que je déclare void * reader();alors au pthread_create(&thread1,null,reader,reader_arg)lieu depthread_create(&thread1,null,&reader,reader_arg)
user9515151
1
@Scheff: Ou même auto function() -> void*(C ++). :)
Jarod42
3
Ou un pointeur vers la fonction qui renvoie le pointeur vers la fonction C'est à cela que typedefsert ... ;-)
Andrew Henle
1
@AndrewHenle Avec typedef il n'y a pas de problème. Un problème survient lorsque les déclarations sont utilisées sans typedef ni déclaration d'alias. :)
Vlad de Moscou
7

Chaque fois que je ne suis pas sûr des problèmes de syntaxe C, j'aime utiliser l' utilitaire cdecl ( version en ligne ) pour interpréter pour moi. Il traduit entre la syntaxe C et l'anglais.

Par exemple, je saisis votre exemple void *foo()et il est revenu

déclarer foo comme fonction renvoyant le pointeur à void

Pour voir à quoi ressemblerait l'autre syntaxe, je saisis declare foo as pointer to function returning voidet il est retourné

void (* foo) ()

Cela devient particulièrement utile lorsque vous disposez de plusieurs niveaux de typecasts, d'étoiles ou de crochets dans une seule expression.

bta
la source
2

Il s'agit d'une fonction renvoyant un pointeur vers void.

Pensez à votre déclaration de cette façon:

void *(function());

Ce serait une fonction retournant void(ou rien):

void (*function2)();

Pensez à la déclaration ci-dessus de cette façon:

void ((*function2)());

Un moyen beaucoup plus simple de les écrire est d'utiliser typedefs:

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

function_returning_void_pointer function;
function_returning_nothing *function2;

Cela élimine généralement la confusion autour des pointeurs de fonction et est beaucoup plus facile à lire.

SS Anne
la source
0

Les déclarations en C / C ++ sont lues de l'identifiant vers l'extérieur suivant la priorité de l'opérateur .

Un rapide coup d'œil au tableau de priorité des opérateurs C / C ++ dans wikipedia révèle que l'opérateur d'appel de fonction ()a une priorité plus élevée que l'opérateur d'indirection *. Ainsi, vos déclarations de fonction se lisent comme suit:

  • Commencez par l'identifiant: functionest

  • function() une fonction qui ne prend aucun argument

  • void* function()et renvoie a void*.

Ce principe général s'applique également aux déclarations de tableau (a []également une priorité plus élevée que *) et aux combinaisons des deux. Donc

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

est lu comme

  • arr est
  • arr[42] un tableau de 42 éléments qui sont
  • *arr[42] pointeurs vers
  • (*arr[42])() fonctions qui ne prennent aucun argument et
  • int *(*arr[42])()retourner un int*.

Il faut un peu de temps pour s'y habituer, mais une fois que vous avez compris le principe, il est facile de lire ces déclarations sans ambiguïté.

cmaster - réintégrer monica
la source