![]()
Récréation ![]()
![]()
![]()
![]()
![]()
Suivant: Les entrées-sorties Début: Relations entre tableaux et Précédent: Tableau et pointeur, c'est
Récréation
En illustration sur les bizarreries des tableaux dans le langage C, voici la contribution de David Korn (le créateur du korn shell) à la compétition du code C le plus obscur (IOCCC) de 1987 :main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}Non, ce programme n'imprime pas have fun with unix ou quelque chose de ce genre ! Le lecteur est invité à essayer d'élucider ce programme (oui, il imprime quelque chose, mais quoi ?) la solution est donnée à la page suivante.
Voici les clés de la compréhension :
- 1.
- Tout compilateur C possède un certain nombre de constantes prédéfinies dépendant de l'architecture de la machine sur laquelle il s'exécute. En particulier, tout compilateur pour machine UNIX prédéfini la constante unix avec comme valeur 1. Donc le programme est équivalent à :
main() { printf(&1["\021%six\012\0"],(1)["have"]+"fun"-0x60);}- 2.
- Si on se souvient qu'on a vu en 4.2 que pour un tableau t,
t[i]
est équivalent ài[t]
, on voit que1["\021%six\012\0"]
est équivalent à"\021%six\012\0"[1]
et(1)["have"]
à"have"[1]
. Donc&1["\021%six\012\0"]
est l'adresse du caractère%
dans la chaîne"\021%six\012\0"
et"have"[1]
est le caractère'a'
. On peut donc réécrire le programme :main() { printf("%six\012\0", 'a' + "fun" -0x60);}- 3.
- La fin d'une chaîne est signalée par un caractère null (
\0
) et le compilateur en met un à la fin de chaque chaîne littérale. Celui qui est ici est donc inutile. D'autre part, il existe une notation plus parlante pour le caractère de code\012
(c'est à dire new line), il s'agit de la notation\n
. Le programme peut donc se réécrire :main() { printf("%six\n", 'a' + "fun" -0x60);}- 4.
- Le caractère
'a'
a pour code ASCII 0x61, donc'a' -0x60
est égal à 1. Réécrivons le programme :main() { printf("%six\n","fun" + 1); }- 5.
"fun" + 1
est l'adresse du caractère u dans la chaîne"fun"
, le programme devient donc :main() { printf("%six\n","un"); }il imprime donc"unix\n"
.
30/9/1997