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.


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 )() )();

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.


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.


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é.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.