¿Qué hace este programa?
main(_){write(read(0,&_,1)&&main());}
Antes lo analizamos, vamos a Prettify que:
main(_) {
write (read(0, &_, 1) && main());
}
En primer lugar, usted debe saber que _
es un nombre de variable válido, aunque muy feo.Vamos a cambiarlo:
main(argc) {
write(read(0, &argc, 1) && main());
}
A continuación, se da cuenta de que el tipo de retorno de una función, y el tipo de un parámetro son opcionales en C (pero no en C++):
int main(int argc) {
write(read(0, &argc, 1) && main());
}
A continuación, entender cómo los valores de retorno funcionan Para ciertos tipos de CPU, el valor de retorno siempre se almacena en los mismos registros (EAX en x86, por ejemplo). Por lo tanto, si omite una instrucción return
, el valor de retorno es probable que sea la función más reciente devuelta.
int main(int argc) {
int result = write(read(0, &argc, 1) && main());
return result;
}
La llamada a read
es más o menos evidente: se lee desde estándar en (descriptor de fichero 0), en la memoria situada en &argc
, por 1
byte. Devuelve 1
si la lectura fue exitosa y 0 en caso contrario.
&&
es el operador lógico "y". Evalúa su lado derecho si y solo si su lado izquierdo es "verdadero" (técnicamente, cualquier valor distinto de cero). El resultado de la expresión &&
es int
, que siempre es 1 (para "verdadero") o 0 (para falso).
En este caso, el lado derecho invoca main
sin argumentos. Llamar al main
sin argumentos después de declararlo con 1 argumento es un comportamiento indefinido. Sin embargo, a menudo funciona, siempre y cuando no le importe el valor inicial del parámetro argc
.
El resultado del &&
se pasa luego al write()
. Entonces, nuestro código ahora se ve así:
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result);
return result;
}
Hmm. Un vistazo rápido a las páginas del manual revela que write
toma tres argumentos, no uno. Otro caso de comportamiento indefinido. Al igual que llamar al main
con muy pocos argumentos, no podemos predecir qué write
recibirá para su segundo y tercer argumentos. En las computadoras típicas, obtendrán algo, pero no podemos saber con certeza qué. (En computadoras atípicas, pueden suceder cosas extrañas). El autor confía en write
para recibir lo que previamente había almacenado en la pila de memoria. Y, él confía en que es el segundo y tercer argumentos para leer.
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result, &argc, 1);
return result;
}
fijación de la llamada no válida a main
, y añadiendo cabeceras, y la ampliación de la &&
tenemos:
#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;
}
Conclusiones
Este programa no funcionará como se espera en muchas computadoras Incluso si usa la misma computadora que el autor original, es posible que no funcione en un sistema operativo diferente. Incluso si usa la misma computadora y el mismo sistema operativo, no funcionará en muchos compiladores. Incluso si usa el mismo compilador de la computadora y el mismo sistema operativo, es posible que no funcione si cambia los indicadores de la línea de comando del compilador.
Como dije en los comentarios, la pregunta no tiene una respuesta válida.Si encontró un organizador del concurso o un juez del concurso que diga lo contrario, no los invite a su próximo concurso.
Ese programa no se compilará en C++. Eliminando la etiqueta C++. –
@ Robᵩ Ah gracias. No tuve cuidado. – RaunakS
Incluso en C, ese programa invoca comportamiento indefinido de múltiples maneras. El resultado es predecible solo para compiladores específicos dirigidos a tipos específicos de CPU (incluso en codegolf, este programa solo hace algo interesante en un nivel de optimización específico). Corrija las respuestas a "¿Qué hace este programa?" incluya "depende", "lo que sea que quiera" y "lo despiden". –