Cosa fa questo programma?
main(_){write(read(0,&_,1)&&main());}
Prima lo analizziamo, diamo anche più elegante:
main(_) {
write (read(0, &_, 1) && main());
}
In primo luogo, si deve sapere che _
è un nome di variabile valido, sia pure brutto.Cambiamo esso:
main(argc) {
write(read(0, &argc, 1) && main());
}
successivo, si rende conto che il tipo di ritorno di una funzione, e il tipo di un parametro sono opzionali in C (ma non in C++):
int main(int argc) {
write(read(0, &argc, 1) && main());
}
Avanti, capire come i valori di ritorno funzionano. Per determinati tipi di CPU, il valore di ritorno è sempre memorizzato negli stessi registri (EAX su x86, ad esempio). Pertanto, se si omette un'istruzione return
, il valore restituito è probabile che sia che corrisponde alla funzione restituita più recente.
int main(int argc) {
int result = write(read(0, &argc, 1) && main());
return result;
}
La chiamata a read
è più o meno evidente: si legge da standard (descrittore di file 0), nella memoria situato a &argc
, per 1
di byte. Restituisce 1
se la lettura ha avuto esito positivo e 0 in caso contrario.
&&
è l'operatore logico "e". Valuta il suo lato destro se e solo se il lato sinistro è "vero" (tecnicamente, qualsiasi valore diverso da zero). Il risultato dell'espressione &&
è un int
che è sempre 1 (per "true") o 0 (per false).
In questo caso, il lato destro invoca main
senza argomenti. Chiamare main
senza argomenti dopo averlo dichiarato con 1 argomento non è un comportamento definito. Tuttavia, spesso funziona, a patto che non ti interessi il valore iniziale del parametro argc
.
Il risultato dello &&
viene quindi passato a write()
. Quindi, il nostro codice ora sembra:
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result);
return result;
}
Hmm. Una rapida occhiata alle pagine man rivela che lo write
accetta tre argomenti, non uno. Un altro caso di comportamento indefinito. Proprio come chiamare lo main
con troppo pochi argomenti, non possiamo prevedere cosa riceverà write
per il suo secondo e terzo argomento. Sui computer tipici, riceveranno qualcosa di, ma non possiamo sapere per certo cosa. (Su computer atipici, possono accadere cose strane.) L'autore si basa su write
per ricevere qualsiasi cosa precedentemente memorizzata nella pila di memoria. E, si basa su che è il secondo e il terzo argomento da leggere.
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result, &argc, 1);
return result;
}
Fissaggio della chiamata non valida per main
, e l'aggiunta di intestazioni, e ampliando la &&
abbiamo:
#include <unistd.h>
int main(int argc, int argv) {
int result;
result = read(0, &argc, 1);
if(result) result = main(argc, argv);
result = write(result, &argc, 1);
return result;
}
Conclusioni
Questo programma non funzionerà come previsto su molti computer. Anche se si utilizza lo stesso computer dell'autore originale, potrebbe non funzionare su un sistema operativo diverso. Anche se si utilizza lo stesso computer e lo stesso sistema operativo, non funzionerà su molti compilatori. Anche se si utilizza lo stesso compilatore e il medesimo sistema operativo, potrebbe non funzionare se si modificano i flag della riga di comando del compilatore.
Come ho detto nei commenti, la domanda non ha una risposta valida.Se hai trovato un organizzatore del concorso o un giudice del concorso che dice diversamente, non invitarlo al tuo prossimo concorso.
Questo programma non verrà compilato in C++. Rimozione del tag C++. –
@ Robᵩ Ah grazie. Sono stato incurante. – RaunakS
Anche in C, quel programma richiama comportamenti indefiniti in più modi. Il risultato è prevedibile solo per compilatori specifici che prendono di mira tipi specifici di CPU (anche su codegolf, questo programma fa qualcosa di interessante a un livello di ottimizzazione specifico). Risposte corrette a "Cosa fa questo programma?" include "Dipende", "Qualunque cosa voglia" e "Ti fa licenziare". –