C90 (gcc), 46 octets
r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}
L'entrée s'effectue via des arguments de ligne de commande (un entier par argument), la sortie via le code de sortie .
Essayez-le en ligne!
Comment ça fonctionne
r est une variable globale. Son type par défaut est int et, étant global, sa valeur par défaut est 0 .
L'argument fonction c par défaut int ainsi. Il contiendra l'entier n + 1 pour les tableaux de n booléens; le premier argument de main est toujours le chemin de l'exécutable.
L'argument de la fonction v est déclaré comme int**
. Le type réel de v sera char**
, mais comme nous n'examinerons que le bit le moins significatif de chaque argument pour distinguer les caractères 0 (point de code 48 ) et 1 (point de code 49 ), cela ne sera pas important pour little-endian Machines.
La boucle while décrémente c et la compare à 0 . Une fois que c atteint 0 , nous sortirons de la boucle. Cela n'est nécessaire que si le tableau ne contient pas de 0 .
Tant que 0<--c
renvoie 1 , nous prenons le c ème argument de ligne de commande ( v[c]
) et extrayons son premier caractère en déréférencant le pointeur ( *
). Nous prenons l'ET au bit ET du booléen 0<--c
et le point de code du caractère (ainsi que trois octets parasites qui le suivent), de sorte que la condition retourne 0 une fois qu'un 0 est rencontré, sortant de la boucle.
Dans le cas restant, alors que les arguments de ligne de commande sont à 1 , r++
incrémente r de 1 , en comptant ainsi le nombre de 1 en fin de chaîne .
Enfin, c=r
stocke la valeur calculée de r dans c . Avec les paramètres par défaut, le compilateur optimise et supprime l’affectation; il génère effectivement l' movl %eax, -4(%rbp)
instruction. Étant donné que ret
renvoie la valeur du registre EAX, cela génère la sortie souhaitée.
Notez que ce code ne fonctionne pas avec C99, qui renvoie 0 du principal si la fin du principal est atteinte.
01100
?