Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :

next up previous contents index
Next: Le préprocesseur Up: Les expressions Previous: Sémantique des expressions

Sous-sections

Récréation

  Voici en illustration de l'opérateur ~, la contribution de Jack Applin a la compétition du code C le plus obscur ( IOCCC) de 1986. Ce programme a la propriété extraordinaire d'être un source valide à la fois pour le shell /bin/sh, le langage C et FORTRAN ! Voici le source :
cat =13 /*/ >/dev/null 2>&1; echo "Hello, world!"; exit
*
*  This program works under cc, f77, and /bin/sh.
*
*/; main() {
      write(
cat-~-cat
     /*,'(
*/
     ,"Hello, world!"
     ,
cat); putchar(~-~-~-cat); } /*
     ,)')
      end
*/

La version shell

La commande cat =13 est une commande incorrecte (à cause du blanc entre cat et le signe =), mais comme l'erreur standard est redirigée sur /dev/null, le message d'erreur n'apparaît pas. Ensuite, l'echo imprime << Hello world >>, puis le shell fait exit. Le reste du source lui est donc indifférent. Ensuite, les deux versions C et fortran sont mélangées grâce à un emploi judicieux des commentaires (en fortran, toute ligne commençant par * ou c est un commentaire).

La version fortran

Une fois débarrassé des commentaires fortran, le source devient :
      write( *,'("Hello, world!")')
      end
ce qui imprime << Hello world >>.

La version C

Après nettoyage des commentaires C, le source original devient :
cat =13 ;
main()
{
write( cat-~-cat ,"Hello, world!" , cat);
putchar(~-~-~-cat); 
}

La déclaration cat =13 ; est valide en C K&R mais obsolète en ANSI C : elle est équivalente à int cat =13 ; Cette forme est cependant encore généralement acceptée (avec un warning) par les compilateurs. La suite ne fonctionne correctement que sur une machine satisfaisant aux deux contraintes suivantes :

1.
être une machine UNIX pour disposer de l'appel noyau write ;
2.
avoir les entiers négatifs représentés en complément à 2. Dans ce cas en effet, ~-x vaut x - 1.
Donc cat-~-cat vaut 1 qui, en premier paramètre de write désigne la sortie standard, et ~-~-~-13 vaut 10 (le code de newline). Le troisième paramètre passé à write doit être la longueur de la chaîne à imprimer, ici 13 qui est bien la longueur de Hello, world!. Au final, ce programme imprime << Hello world >>.
next up previous contents index
Next: Le préprocesseur Up: Les expressions Previous: Sémantique des expressions
Bernard Cassagne
1998-12-09
Contacter le responsable de la rubrique C