N'écrivez jamais de code comme ça.
Pour j<1000
, j/1000
vaut zéro (division entière). Alors:
(&main + (&exit - &main)*(j/1000))(j+1);
est équivalent à:
(&main + (&exit - &main)*0)(j+1);
Lequel est:
(&main)(j+1);
Qui appelle main
avec j+1
.
Si j == 1000
, alors les mêmes lignes sortent comme:
(&main + (&exit - &main)*1)(j+1);
Ce qui se résume à
(&exit)(j+1);
Ce qui est exit(j+1)
et quitte le programme.
(&exit)(j+1)
et exit(j+1)
sont essentiellement la même chose - citant C99 §6.3.2.1 / 4:
Un désignateur de fonction est une expression qui a un type de fonction. Sauf s'il s'agit de l'opérande de l'opérateur sizeof ou de l' opérateur unaire & , un désignateur de fonction de type " type de retour de fonction " est converti en une expression de type " pointeur vers type de retour de fonction ".
exit
est un désignateur de fonction. Même sans l'opérateur d' &
adresse unaire de, il est traité comme un pointeur vers une fonction. (Le &
juste le rend explicite.)
Et les appels de fonction sont décrits au §6.5.2.2 / 1 et suivants:
L'expression qui désigne la fonction appelée doit avoir un pointeur de type sur la fonction renvoyant void ou renvoyant un type d'objet autre qu'un type tableau.
Cela exit(j+1)
fonctionne à cause de la conversion automatique du type de fonction en type pointeur vers fonction, et (&exit)(j+1)
fonctionne également avec une conversion explicite en type pointeur vers fonction.
Cela étant dit, le code ci-dessus n'est pas conforme ( main
prend soit deux arguments, soit aucun), et &exit - &main
est, je crois, indéfini selon le §6.5.6 / 9:
Lorsque deux pointeurs sont soustraits, les deux doivent pointer vers des éléments du même objet tableau , ou un après le dernier élément de l'objet tableau; ...
L'addition (&main + ...)
serait valide en soi, et pourrait être utilisée, si la quantité ajoutée était nulle, puisque le §6.5.6 / 7 dit:
Pour les besoins de ces opérateurs, un pointeur vers un objet qui n'est pas un élément d'un tableau se comporte de la même manière qu'un pointeur vers le premier élément d'un tableau de longueur un avec le type de l'objet comme type d'élément.
Donc, ajouter zéro à ce &main
serait correct (mais pas très utile).
main
en C ++.